home *** CD-ROM | disk | FTP | other *** search
/ Shareware Super Platinum 8 / Shareware Super Platinum 8.iso / mac / WIN_PRO / DS-1.ZIP;1 / RTT.ZIP / RTTOUT.C < prev    next >
Encoding:
C/C++ Source or Header  |  1992-02-10  |  114.0 KB  |  3,600 lines

  1. #include "rtt.h"
  2.  
  3. #define NotId 0  /* declarator is not simple identifier */
  4. #define IsId  1  /* declarator is simple identifier */
  5.  
  6. #define OrdFunc -1   /* indicates ordinary C function - non-token value */
  7.  
  8. /*
  9.  * VArgAlwnc - allowance for the variable part of an argument list in the
  10.  *  most general version of an operation. If it is too small, storage must
  11.  *  be malloced. 3 was choosen because over 90 percent of all writes have
  12.  *  3 or fewer arguments. It is possible that 4 would be a better number,
  13.  *  but 5 is probably overkill.
  14.  */
  15. #define VArgAlwnc 3
  16.  
  17. /*
  18.  * Prototypes for static functions.
  19.  */
  20. hidden novalue cnv_fnc       Params((struct token *t, struct node *cnv_typ,
  21.                                struct node *src, struct node *dflt,
  22.                                struct node *dest, int indent));
  23. hidden novalue chk_conj      Params((struct node *n));
  24. hidden novalue chk_nl        Params((int indent));
  25. hidden novalue chk_rsltblk   Params((int indent));
  26. hidden novalue comp_def      Params((struct node *n));
  27. hidden int     does_call     Params((struct node *expr));
  28. hidden novalue failure       Params((int indent, int brace));
  29. hidden novalue interp_def    Params((struct node *n));
  30. hidden novalue len_sel       Params((struct node *sel, int *strt_prms,
  31.                                int *end_prms, int indent));
  32. hidden novalue line_dir      Params((int nxt_line, char *new_fname));
  33. hidden int     only_proto    Params((struct node *n));
  34. hidden novalue parm_locs     Params((struct sym_entry *op_params));
  35. hidden novalue parm_tnd      Params((struct sym_entry *sym));
  36. hidden novalue prt_runerr    Params((struct node *n, int indent));
  37. hidden novalue prt_tok       Params((struct token *t, int indent));
  38. hidden novalue prt_var       Params((struct node *n, int indent));
  39. hidden int     real_def      Params((struct node *n));
  40. hidden int     retval_dcltor Params((struct node *dcltor, int indent));
  41. hidden novalue ret_blk       Params((struct token *t, struct node *args,
  42.                                char *constr, char *b_type, int indent));
  43. hidden novalue ret_value     Params((struct token *t, struct node *n,
  44.                                int indent));
  45. hidden novalue rt_walk       Params((struct node *n, int indent, int brace));
  46. hidden novalue spcl_start    Params((struct sym_entry *op_params));
  47. hidden int     tdef_or_extr  Params((struct node *n));
  48. hidden novalue tend_ary      Params((int n));
  49. hidden novalue tend_init     Params((noargs));
  50. hidden novalue tnd_var       Params((struct sym_entry *sym, char *strct_ptr, char *access, int indent));
  51. hidden novalue tok_line      Params((struct token *t, int indent));
  52. hidden novalue typ_asrt      Params((struct token *typ, struct node *desc, int indent));
  53. hidden novalue typ_case      Params((struct node *var, struct node *slct_lst,
  54.                              struct node *dflt, novalue (*walk)(),
  55.                              int maybe_var, int indent));
  56. hidden novalue untend        Params((int indent));
  57.  
  58. extern char *progname;
  59.  
  60. int op_type = OrdFunc;  /* type of operation */
  61. char lc_letter;         /* f = function, o = operator, k = keyword */
  62. char uc_letter;         /* F = function, O = operator, K = keyword */
  63. char prfx1;             /* 1st char of unique prefix for operation */
  64. char prfx2;             /* 2nd char of unique prefix for operation */
  65. char *fname = "";       /* current source file name */
  66. int line = 0;           /* current source line number */
  67. int nxt_sbuf;           /* next string buffer index */
  68. int nxt_cbuf;           /* next cset buffer index */
  69. int abs_ret = SomeType; /* type from abstract return(s) */
  70.  
  71. int nl = 0;             /* flag indicating the a new-line should be output */
  72. static int no_nl = 0;   /* flag to suppress line directives */
  73.  
  74. static int ntend;       /* number of tended descriptor needed */
  75. static char *tendstrct; /* expression to access struct of tended descriptors */
  76. static char *rslt_loc;  /* expression to access result location */
  77. static int varargs = 0; /* flag: operation takes variable number of arguments */
  78.  
  79. static int no_ret_val;  /* function has return statement with no value */
  80. static struct node *fnc_head; /* header of function being "copied" to output */
  81.  
  82. /*
  83.  * chk_nl - if a new-line is required, output it and indent the next line.
  84.  */
  85. static novalue chk_nl(indent)
  86. int indent;
  87.    {
  88.    int col;
  89.  
  90.    if (nl)  {
  91.       /*
  92.        * new-line required.
  93.        */
  94.       putc('\n', out_file);
  95.       ++line;
  96.       for (col = 0; col < indent; ++col)
  97.          putc(' ', out_file);
  98.       nl = 0;
  99.       }
  100.    }
  101.  
  102. /*
  103.  * line_dir - Output a line directive.
  104.  */
  105. static novalue line_dir(nxt_line, new_fname)
  106. int nxt_line;
  107. char *new_fname;
  108.    {
  109.    char *s;
  110.  
  111.    /*
  112.     * Make sure line directives are desired in the output. Normally,
  113.     *  blank lines surround the directive for readability. However,`
  114.     *  a preceeding blank line is suppressed at the begining of the
  115.     *  output file. In addition, a blank line is suppressed after
  116.     *  the directive if it would force the line number on the directive
  117.     *  to be 0.
  118.     */
  119.    if (line_cntrl) {
  120.       fprintf(out_file, "\n");
  121.       if (line != 0)
  122.          fprintf(out_file, "\n");
  123.       if (nxt_line == 1)
  124.          fprintf(out_file, "#line %d \"", nxt_line);
  125.       else
  126.          fprintf(out_file, "#line %d \"", nxt_line - 1);
  127.       for (s = new_fname; *s != '\0'; ++s) {
  128.          if (*s == '"' || *s == '\\')
  129.             putc('\\', out_file);
  130.          putc(*s, out_file);
  131.          }
  132.       if (nxt_line == 1)
  133.          fprintf(out_file, "\"");
  134.       else
  135.          fprintf(out_file, "\"\n");
  136.       nl = 1;
  137.       --nxt_line;
  138.       }
  139.     else if ((nxt_line > line || fname != new_fname) && line != 0) {
  140.       /*
  141.        * Line directives are disabled, but we are in a situation where
  142.        *  one or two new-lines are desirable.
  143.        */
  144.       if (nxt_line > line + 1 || fname != new_fname)
  145.          fprintf(out_file, "\n");
  146.       nl = 1;
  147.       --nxt_line;
  148.       }
  149.    line = nxt_line;
  150.    fname = new_fname;
  151.    }
  152.  
  153. /*
  154.  * prt_str - print a string to the output file, possibly preceeded by
  155.  *   a new-line and indenting.
  156.  */
  157. novalue prt_str(s, indent)
  158. char *s;
  159. int indent;
  160.    {
  161.    chk_nl(indent);
  162.    fprintf(out_file, "%s", s);
  163.    }
  164.  
  165. /*
  166.  * tok_line - determine if a line directive is needed to synchronize the
  167.  *  output file name and line number with an input token.
  168.  */
  169. static novalue tok_line(t, indent)
  170. struct token *t;
  171. int indent;
  172.    {
  173.    int nxt_line;
  174.  
  175.    /*
  176.     * Line directives may be suppressed at certain points during code
  177.     *  output. This is done either by rtt itself using the no_nl flag, or
  178.     *  for macros, by the preprocessor using a flag in the token.
  179.     */
  180.    if (no_nl)
  181.       return;
  182.    if (t->flag & LineChk) {
  183.       /*
  184.        * If blank lines can be used in place of a line directive and no
  185.        *  more than 3 are needed, use them. If the line number and file
  186.        *  name are correct, but we need a new-line, we must output a
  187.        *  line directive so the line number is reset after the "new-line".
  188.        */
  189.       nxt_line = t->line;
  190.       if (fname != t->fname  || line > nxt_line || line + 2 < nxt_line)
  191.          line_dir(nxt_line, t->fname);
  192.       else if (nl && line == nxt_line)
  193.          line_dir(nxt_line, t->fname);
  194.       else if (line != nxt_line) {
  195.          nl = 1;
  196.          --nxt_line;
  197.          while (line < nxt_line) { /* above condition limits # interations */
  198.             putc('\n', out_file);
  199.             ++line;
  200.             }
  201.          }
  202.       }
  203.    chk_nl(indent);
  204.    }
  205.  
  206. /*
  207.  * prt_tok - print a token.
  208.  */
  209. static novalue prt_tok(t, indent)
  210. struct token *t;
  211. int indent;
  212.    {
  213.    char *s;
  214.  
  215.    tok_line(t, indent); /* synchronize file name and line number */
  216.  
  217.    /*
  218.     * Most tokens contain a string of their exact image. However, string
  219.     *  and character literals lack the surrounding quotes.
  220.     */
  221.    s = t->image;
  222.    switch (t->tok_id) {
  223.       case StrLit:
  224.          fprintf(out_file, "\"%s\"", s);
  225.          break;
  226.       case LStrLit:
  227.          fprintf(out_file, "L\"%s\"", s);
  228.          break;
  229.       case CharConst:
  230.          fprintf(out_file, "'%s'", s);
  231.          break;
  232.       case LCharConst:
  233.          fprintf(out_file, "L'%s'", s);
  234.          break;
  235.       default:
  236.          fprintf(out_file, "%s", s);
  237.       }
  238.    }
  239.  
  240. /*
  241.  * untend - output code to removed the tended descriptors in this
  242.  *  function from the global tended list.
  243.  */
  244. static novalue untend(indent)
  245. int indent;
  246.    {
  247.    ForceNl();
  248.    prt_str("tend = ", indent);
  249.    fprintf(out_file, "%s.previous;", tendstrct);
  250.    ForceNl();
  251.    /*
  252.     * For varargs operations, the tended structure might have been
  253.     *  malloced. If so, it must be freed.
  254.     */
  255.    if (varargs) {
  256.       prt_str("if (r_tendp != (struct tend_desc *)&r_tend)", indent);
  257.       ForceNl();
  258.       prt_str("free((pointer)r_tendp);", 2 * indent);
  259.       }
  260.    }
  261.  
  262. /*
  263.  * tnd_var - output an expression to accessed a tended variable.
  264.  */
  265. static novalue tnd_var(sym, strct_ptr, access, indent)
  266. struct sym_entry *sym;
  267. char *strct_ptr;
  268. char *access;
  269. int indent;
  270.    {
  271.    /*
  272.     * A variable that is a specific block pointer type must be cast
  273.     *  to that pointer type in such a way that it can be used as either
  274.     *  an lvalue or an rvalue:  *(struct b_??? **)&???.vword.bptr
  275.     */
  276.    if (strct_ptr != NULL) {
  277.       prt_str("(*(struct ", indent);
  278.       prt_str(strct_ptr, indent);
  279.       prt_str("**)&", indent);
  280.       }
  281.  
  282.    if (sym->id_type & ByRef) {
  283.       /*
  284.        * The tended variable is being accessed indirectly through
  285.        *  a pointer (that is, it is accessed as the argument to a body
  286.        *  function); dereference its identifier.
  287.        */
  288.       prt_str("(*", indent);
  289.       prt_str(sym->image, indent);
  290.       prt_str(")", indent);
  291.       }
  292.    else {
  293.       if (sym->t_indx >= 0) {
  294.          /*
  295.           * The variable is accessed directly as part of the tended structure.
  296.           */
  297.          prt_str(tendstrct, indent);
  298.          fprintf(out_file, ".d[%d]", sym->t_indx);
  299.          }
  300.       else {
  301.          /*
  302.           * This is a direct access to an operation parameter.
  303.           */
  304.          prt_str("r_args[", indent);
  305.          fprintf(out_file, "%d]", sym->u.param_info.param_num + 1);
  306.          }
  307.       }
  308.    prt_str(access, indent);  /* access the vword for tended pointers */
  309.    if (strct_ptr != NULL)
  310.       prt_str(")", indent);
  311.    }
  312.  
  313. /*
  314.  * prt_var - print a variable.
  315.  */
  316. static novalue prt_var(n, indent)
  317. struct node *n;
  318. int indent;
  319.    {
  320.    struct token *t;
  321.    struct sym_entry *sym;
  322.  
  323.    t = n->tok;
  324.    tok_line(t, indent); /* synchronize file name and line nuber */
  325.    sym = n->u[0].sym;
  326.    switch (sym->id_type & ~ByRef) {
  327.       case TndDesc:
  328.          /*
  329.           * Simple tended descriptor.
  330.           */
  331.          tnd_var(sym, NULL, "", indent);
  332.          break;
  333.       case TndStr:
  334.          /*
  335.           * Tended character pointer.
  336.           */
  337.          tnd_var(sym, NULL, ".vword.sptr", indent);
  338.          break;
  339.       case TndBlk:
  340.          /*
  341.           * Tended block pointer.
  342.           */
  343.          tnd_var(sym, sym->u.tnd_var.blk_name, ".vword.bptr",
  344.             indent);
  345.          break;
  346.       case RtParm:
  347.       case DrfPrm:
  348.          switch (sym->u.param_info.cur_loc) {
  349.             case PrmTend:
  350.                /*
  351.                 * Simple tended parameter.
  352.                 */
  353.                tnd_var(sym, NULL, "", indent);
  354.                break;
  355.             case PrmCStr:
  356.                /*
  357.                 * Parameter converted to a (tended) string.
  358.                 */
  359.                tnd_var(sym, NULL, ".vword.sptr", indent);
  360.                break;
  361.             case PrmInt:
  362.                /*
  363.                 * Parameter converted to a C integer.
  364.                 */
  365.                chk_nl(indent);
  366.                fprintf(out_file, "r_i%d", sym->u.param_info.param_num);
  367.                break;
  368.             case PrmDbl:
  369.                /*
  370.                 * Parameter converted to a C double.
  371.                 */
  372.                chk_nl(indent);
  373.                fprintf(out_file, "r_d%d", sym->u.param_info.param_num);
  374.                break;
  375.             default:
  376.                errt2(t, "Conflicting conversions for: ", t->image);
  377.             }
  378.          break;
  379.       case RtParm | VarPrm:
  380.       case DrfPrm | VarPrm:
  381.          /*
  382.           * Parameter representing variable part of argument list.
  383.           */
  384.          prt_str("(&", indent);
  385.          if (sym->t_indx >= 0)
  386.             fprintf(out_file, "%s.d[%d])", tendstrct, sym->t_indx);
  387.          else
  388.             fprintf(out_file, "r_args[%d])", sym->u.param_info.param_num + 1);
  389.          break;
  390.       case VArgLen:
  391.          /*
  392.           * Length of variable part of argument list.
  393.           */
  394.          prt_str("(r_nargs - ", indent);
  395.          fprintf(out_file, "%d)", params->u.param_info.param_num);
  396.          break;
  397.       case RsltLoc:
  398.          /*
  399.           * "result" the result location of the operation.
  400.           */
  401.          prt_str(rslt_loc, indent);
  402.          break;
  403.       case Label:
  404.          /*
  405.           * Statement label.
  406.           */
  407.          prt_str(sym->image, indent);
  408.          break;
  409.       case OtherDcl:
  410.          /*
  411.           * Some other type of variable: accessed by identifier. If this
  412.           *  is a body function, it may be passed by reference and need
  413.           *  a level of pointer dereferencing.
  414.           */
  415.          if (sym->id_type & ByRef)
  416.             prt_str("(*",indent);
  417.          prt_str(sym->image, indent);
  418.          if (sym->id_type & ByRef)
  419.             prt_str(")",indent);
  420.          break;
  421.       }
  422.    }
  423.  
  424. /*
  425.  * does_call - determine if an expression contains a function call by
  426.  *  walking its syntax tree.
  427.  */
  428. static int does_call(expr)
  429. struct node *expr;
  430.    {
  431.    int i;
  432.  
  433.    if (expr == NULL)
  434.       return 0;
  435.    if (expr->nd_id == BinryNd && expr->tok->tok_id == ')')
  436.       return 1;      /* found a function call */
  437.    if (expr->nd_id != SymNd)
  438.       for (i = 0; i < NChildren; ++i)
  439.          if (does_call(expr->u[i].child))
  440.              return 1;
  441.    return 0;
  442.    }
  443.  
  444. /*
  445.  * prt_runerr - print code to implement runerr().
  446.  */
  447. static novalue prt_runerr(n, indent)
  448. struct node *n;
  449. int indent;
  450.    {
  451.    if (op_type == OrdFunc)
  452.       errt1(n->tok, "'runerr' may not be used in an ordinary C function");
  453.  
  454.    tok_line(n->tok, indent);  /* synchronize file name and line number */
  455.    prt_str("{", indent);
  456.    ForceNl();
  457.    prt_str("err_msg(", indent);
  458.    c_walk(n->u[0].child, indent, 0);      /* error number */
  459.    if (n->u[1].child == NULL)
  460.       prt_str(", NULL);", indent);        /* no offending value */
  461.    else {
  462.       prt_str(", &(", indent);
  463.       c_walk(n->u[1].child, indent, 0);   /* offending value */
  464.       prt_str("));", indent);
  465.       }
  466.    /*
  467.     * Handle error conversion. Indicate that operation may fail because
  468.     *  of error conversion and produce the necessary code.
  469.     */
  470.    cur_impl->ret_flag |= DoesEFail;
  471.    failure(indent, 1);
  472.    prt_str("}", indent);
  473.    }
  474.  
  475. /*
  476.  * typ_code - convert token for a type to a string that can be used to
  477.  *  output "T_" or "D_" type codes.
  478.  */
  479. char *typ_code(typ)
  480. struct token *typ;
  481.    {
  482.    switch (typ->tok_id) {
  483.       case Null:
  484.          return "Null";
  485.       case Cset:
  486.          return "Cset";
  487.       case Integer:
  488.          return "Integer";
  489.       case Real:
  490.          return "Real";
  491.       case File:
  492.          return "File";
  493.       case List:
  494.          return "List";
  495.       case Set:
  496.          return "Set";
  497.       case Table:
  498.          return "Table";
  499.       case Record:
  500.          return "Record";
  501.       case Procedure:
  502.          return "Proc";
  503.       case Co_expression:
  504.          return "Coexpr";
  505.       case Tvsubs:
  506.          return "Tvsubs";
  507.       case Tvtbl:
  508.          return "Tvtbl";
  509.       case Kywdint:
  510.          return "Kywdint";
  511.       case Kywdpos:
  512.          return "Kywdpos";
  513.       case Kywdsubj:
  514.          return "Kywdsubj";
  515.       case Empty_type:
  516.          errt1(typ, "it is meaningless to assert a type of empty_type");
  517.       default:
  518.          return NULL;
  519.       }
  520.    }
  521.  
  522. /*
  523.  * Produce a C conditional expression to check a descriptor for a
  524.  *  particular type.
  525.  */
  526. static novalue typ_asrt(typ, desc, indent)
  527. struct token *typ;
  528. struct node *desc;
  529. int indent;
  530.    {
  531.    tok_line(typ, indent);
  532.    switch (typ->tok_id) {
  533.       case String:
  534.          /*
  535.           * Check dword for the absense of a "not qualifer" flag.
  536.           */
  537.          prt_str("(!((", indent);
  538.          c_walk(desc, indent, 0);
  539.          prt_str(").dword & F_Nqual))", indent);
  540.          break;
  541.       case Variable:
  542.          /*
  543.           * Check dword for the presense of a "variable" flag.
  544.           */
  545.          prt_str("(((", indent);
  546.          c_walk(desc, indent, 0);
  547.          prt_str(").dword & D_Var) == D_Var)", indent);
  548.          break;
  549.       case Integer:
  550.          /*
  551.           * If large integers are supported, an integer can be either
  552.           *  an ordinary integer or a large integer.
  553.           */
  554.          ForceNl();
  555.          prt_str("#ifdef LargeInts", 0);
  556.          ForceNl();
  557.          prt_str("(((", indent);
  558.          c_walk(desc, indent, 0);
  559.          prt_str(").dword == D_Integer) || ((", indent);
  560.          c_walk(desc, indent, 0);
  561.          prt_str(").dword == D_Lrgint))", indent);
  562.          ForceNl();
  563.          prt_str("#else\t\t\t\t\t/* LargeInts */", 0);
  564.          ForceNl();
  565.          prt_str("((", indent);
  566.          c_walk(desc, indent, 0);
  567.          prt_str(").dword == D_", indent);
  568.          prt_str(typ_code(typ), indent);
  569.          prt_str(")", indent);
  570.          ForceNl();
  571.          prt_str("#endif\t\t\t\t\t/* LargeInts */", 0);
  572.          ForceNl();
  573.          break;
  574.       default:
  575.          /*
  576.           * Check dword for a specific type code.
  577.           */
  578.          prt_str("((", indent);
  579.          c_walk(desc, indent, 0);
  580.          prt_str(").dword == D_", indent);
  581.          prt_str(typ_code(typ), indent);
  582.          prt_str(")", indent);
  583.       }
  584.    }
  585.  
  586. /*
  587.  * retval_dcltor - convert the "declarator" part of function declaration
  588.  *  into a declarator for the variable "r_retval" of the same type
  589.  *  as the function result type, outputing the new declarator. This
  590.  *  variable is a temporary location to store the result of the argument
  591.  *  to a C return statement.
  592.  */
  593. static int retval_dcltor(dcltor, indent)
  594. struct node *dcltor;
  595. int indent;
  596.    {
  597.    int flag;
  598.  
  599.    switch (dcltor->nd_id) {
  600.       case ConCatNd:
  601.          c_walk(dcltor->u[0].child, indent, 0);
  602.          retval_dcltor(dcltor->u[1].child, indent);
  603.          return NotId;
  604.       case PrimryNd:
  605.          /*
  606.           * We have reached the function name. Replace it with "r_retval"
  607.           *  and tell caller we have found it.
  608.           */
  609.          prt_str("r_retval", indent);
  610.          return IsId;
  611.       case PrefxNd:
  612.          /*
  613.           * (...)
  614.           */
  615.          prt_str("(", indent);
  616.          flag = retval_dcltor(dcltor->u[0].child, indent);
  617.          prt_str(")", indent);
  618.          return flag;
  619.       case BinryNd:
  620.          if (dcltor->tok->tok_id == ')') {
  621.             /*
  622.              * Function declaration. If this is the declarator that actually
  623.              *  defines the function being processed, discard the paramater
  624.              *  list including parentheses.
  625.              */
  626.             if (retval_dcltor(dcltor->u[0].child, indent) == NotId) {
  627.                prt_str("(", indent);
  628.                c_walk(dcltor->u[1].child, indent, 0);
  629.                prt_str(")", indent);
  630.                }
  631.             }
  632.          else {
  633.             /*
  634.              * Array.
  635.              */
  636.             retval_dcltor(dcltor->u[0].child, indent);
  637.             prt_str("[", indent);
  638.             c_walk(dcltor->u[1].child, indent, 0);
  639.             prt_str("]", indent);
  640.             }
  641.          return NotId;
  642.       }
  643.    err1("rtt internal error detected in function retval_dcltor()");
  644.    /* NOTREACHED */
  645.    }
  646.  
  647. /*
  648.  * cnv_fnc - produce code to handle RTT cnv: and def: constructs.
  649.  */
  650. static novalue cnv_fnc(t, cnv_typ, src, dflt, dest, indent)
  651. struct token *t;
  652. struct node *cnv_typ;
  653. struct node *src;
  654. struct node *dflt;
  655. struct node *dest;
  656. int indent;
  657.    {
  658.    int dflt_to_ptr;
  659.    int loc;
  660.    int is_cstr;
  661.  
  662.    if (src->nd_id == SymNd && src->u[0].sym->id_type & VarPrm)
  663.       errt1(t, "converting entire variable part of param list not supported");
  664.  
  665.    tok_line(t, indent); /* synchronize file name and line number */
  666.  
  667.    /*
  668.     * Initial assumptions: result of conversion is a tended location
  669.     *   and is not tended C string.
  670.     */
  671.    loc = PrmTend;
  672.    is_cstr = 0;
  673.  
  674.   /*
  675.    * Print the name of the conversion function. If it is a converson
  676.    *  with a default value, determine (through dflt_to_prt) if the
  677.    *  default value is passed by-reference instead of by-value.
  678.    */
  679.    prt_str(cnv_name(cnv_typ, dflt, &dflt_to_ptr), indent);
  680.    prt_str("(", indent);
  681.  
  682.    /*
  683.     * Determine what parameter scope, if any, is established by this
  684.     *  conversion. If the conversion needs a buffer, allocate it and
  685.     *  put it in the argument list.
  686.     */
  687.    if (cnv_typ->nd_id == PrimryNd)
  688.       switch (cnv_typ->tok->tok_id) {
  689.          case C_Integer:
  690.             loc = PrmInt;
  691.             break;
  692.          case C_Double:
  693.             loc = PrmDbl;
  694.             break;
  695.          case C_String:
  696.             is_cstr = 1;
  697.             break;
  698.          case Tmp_string:
  699.             fprintf(out_file, "r_sbuf[%d], ", nxt_sbuf++);
  700.             break;
  701.          case Tmp_cset:
  702.             fprintf(out_file, "&r_cbuf[%d], ", nxt_cbuf++);
  703.             break;
  704.          }
  705.    else {   /* must be exact conversion */
  706.       if (cnv_typ->tok->tok_id == C_Integer)
  707.          loc = PrmInt;
  708.       }
  709.  
  710.    /*
  711.     * Output source of conversion.
  712.     */
  713.    prt_str("&(", indent);
  714.    c_walk(src, indent, 0);
  715.    prt_str("), ", indent);
  716.  
  717.    /*
  718.     * If there is a default value, output it, taking its address if necessary.
  719.     */
  720.    if (dflt != NULL) {
  721.       if (dflt_to_ptr)
  722.          prt_str("&(", indent);
  723.       c_walk(dflt, indent, 0);
  724.       if (dflt_to_ptr)
  725.          prt_str("), ", indent);
  726.       else
  727.          prt_str(", ", indent);
  728.       }
  729.  
  730.    /*
  731.     * Output the destination of the conversion. This may or may not be
  732.     *  the same as the source.
  733.     */
  734.    prt_str("&(", indent);
  735.    if (dest == NULL) {
  736.       /*
  737.        * Convert "in place", changing the location of a paramater if needed.
  738.        */
  739.       if (src->nd_id == SymNd && src->u[0].sym->id_type & (RtParm | DrfPrm)) {
  740.          if (src->u[0].sym->id_type & DrfPrm)
  741.             src->u[0].sym->u.param_info.cur_loc = loc;
  742.          else
  743.             errt1(t, "only dereferenced parameter can be converted in-place");
  744.          }
  745.       else if (loc != PrmTend | is_cstr)
  746.          errt1(t,
  747.             "only ordinary parameters can be converted in-place to C values");
  748.       c_walk(src, indent, 0);
  749.       if (is_cstr) {
  750.          /*
  751.           * The parameter must be accessed as a tended C string, but only
  752.           *  now, after the "destination" code has been produced as a full
  753.           *  descriptor.
  754.           */
  755.          src->u[0].sym->u.param_info.cur_loc = PrmCStr;
  756.          }
  757.       }
  758.    else {
  759.       /*
  760.        * Convert to an explicit destination.
  761.        */
  762.       if (is_cstr) {
  763.          /*
  764.           * Access the destination as a full descriptor even though it
  765.           *  must be declared as a tended C string.
  766.           */
  767.          if (dest->nd_id != SymNd || (dest->u[0].sym->id_type != TndStr &&
  768.                dest->u[0].sym->id_type != TndDesc))
  769.             errt1(t,
  770.              "dest. of C_string conv. must be tended descriptor or char *");
  771.          tnd_var(dest->u[0].sym, NULL, "", indent);
  772.          }
  773.       else
  774.          c_walk(dest, indent, 0);
  775.       }
  776.    prt_str("))", indent);
  777.    }
  778.  
  779. /*
  780.  * cnv_name - produce name of conversion routine. Warning, name is
  781.  *   constructed in a static buffer. Also determine if a default
  782.  *   must be passed "by reference".
  783.  */
  784. char *cnv_name(cnv_typ, dflt, dflt_to_ptr)
  785. struct node *cnv_typ;
  786. struct node *dflt;
  787. int *dflt_to_ptr;
  788.    {
  789.    static char buf[15];
  790.    int by_ref;
  791.  
  792.    /*
  793.     * The names of simple conversion and defaulting conversions have
  794.     *  the same suffixes, but different prefixes.
  795.     */
  796.    if (dflt == NULL)
  797.       strcpy(buf , "cnv_");
  798.    else
  799.        strcpy(buf, "def_");
  800.  
  801.    by_ref = 0;
  802.    if (cnv_typ->nd_id == PrimryNd)
  803.       switch (cnv_typ->tok->tok_id) {
  804.          case Cset:
  805.             strcat(buf, "cset");
  806.             by_ref = 1;
  807.             break;
  808.          case Integer:
  809.             strcat(buf, "int");
  810.             break;
  811.          case Real:
  812.             strcat(buf, "real");
  813.             break;
  814.          case String:
  815.             strcat(buf, "str");
  816.             by_ref = 1;
  817.             break;
  818.          case C_Integer:
  819.             strcat(buf, "c_int");
  820.             break;
  821.          case C_Double:
  822.             strcat(buf, "c_dbl");
  823.             break;
  824.          case C_String:
  825.             strcat(buf, "c_str");
  826.             break;
  827.          case Tmp_string:
  828.             strcat(buf, "tstr");
  829.             by_ref = 1;
  830.             break;
  831.          case Tmp_cset:
  832.             strcat(buf, "tcset");
  833.             by_ref = 1;
  834.             break;
  835.          }
  836.    else {   /* must be exact conversion */
  837.       if (cnv_typ->tok->tok_id == Integer)
  838.          strcat(buf, "eint");
  839.       else  /* C_integer */
  840.          strcat(buf, "ec_int");
  841.       }
  842.    if (dflt_to_ptr != NULL)
  843.       *dflt_to_ptr = by_ref;
  844.    return buf;
  845.    }
  846.  
  847. /*
  848.  * ret_value - produce code to set the result location of an operation
  849.  *  using the expression on a return or suspend.
  850.  */
  851. static novalue ret_value(t, n, indent)
  852. struct token *t;
  853. struct node *n;
  854. int indent;
  855.    {
  856.    struct node *caller;
  857.    struct node *args;
  858.  
  859.    if (n == NULL)
  860.       errt1(t, "there is no default return value for run-time operations");
  861.  
  862.    if (n->nd_id == SymNd && n->u[0].sym->id_type == RsltLoc) {
  863.       /*
  864.        * return/suspend result;
  865.        *
  866.        *   result already where it needs to be.
  867.        */
  868.       return;
  869.       }
  870.  
  871.    if (n->nd_id == PrefxNd && n->tok != NULL) {
  872.       switch (n->tok->tok_id) {
  873.          case C_Integer:
  874.             /*
  875.              * return/suspend C_integer <expr>;
  876.              */
  877.             prt_str(rslt_loc, indent);
  878.             prt_str(".vword.integr = ", indent);
  879.             c_walk(n->u[0].child, indent + IndentInc, 0);
  880.             prt_str(";", indent);
  881.             ForceNl();
  882.             prt_str(rslt_loc, indent);
  883.             prt_str(".dword = D_Integer;", indent);
  884.             chkabsret(t, TypInt);  /* compare return with abstract return */
  885.             return;
  886.          case C_Double:
  887.             /*
  888.              * return/suspend C_double <expr>;
  889.              */
  890.             prt_str(rslt_loc, indent);
  891.             prt_str(".vword.bptr = (union block *)alcreal(", indent);
  892.             c_walk(n->u[0].child, indent + IndentInc, 0);
  893.             prt_str(");", indent + IndentInc);
  894.             ForceNl();
  895.             prt_str(rslt_loc, indent);
  896.             prt_str(".dword = D_Real;", indent);
  897.             /*
  898.              * The allocation of the real block may fail.
  899.              */
  900.             chk_rsltblk(indent);
  901.             chkabsret(t, TypReal); /* compare return with abstract return */
  902.             return;
  903.          case C_String:
  904.             /*
  905.              * return/suspend C_string <expr>;
  906.              */
  907.             prt_str(rslt_loc, indent);
  908.             prt_str(".vword.sptr = ", indent);
  909.             c_walk(n->u[0].child, indent + IndentInc, 0);
  910.             prt_str(";", indent);
  911.             ForceNl();
  912.             prt_str(rslt_loc, indent);
  913.             prt_str(".dword = strlen(", indent);
  914.             prt_str(rslt_loc, indent);
  915.             prt_str(".vword.sptr);", indent);
  916.             chkabsret(t, TypStr); /* compare return with abstract return */
  917.             return;
  918.          }
  919.       }
  920.    else if (n->nd_id == BinryNd && n->tok->tok_id == ')') {
  921.       /*
  922.        * Return value is in form of function call, see if it is really
  923.        *  a descriptor constructor.
  924.        */
  925.       caller = n->u[0].child;
  926.       args = n->u[1].child;
  927.       if (caller->nd_id == PrimryNd || caller->nd_id == SymNd) {
  928.          switch (caller->tok->tok_id) {
  929.             case String:
  930.                /*
  931.                 * return/suspend string(<len>, <char-pntr>);
  932.                 */
  933.                if (args == NULL || args->nd_id != CommaNd ||
  934.                   args->u[0].child->nd_id == CommaNd)
  935.                   errt1(t, "wrong no. of args for string(n, s)");
  936.                prt_str(rslt_loc, indent);
  937.                prt_str(".vword.sptr = ", indent);
  938.                c_walk(args->u[1].child, indent + IndentInc, 0);
  939.                prt_str(";", indent);
  940.                ForceNl();
  941.                prt_str(rslt_loc, indent);
  942.                prt_str(".dword = ", indent);
  943.                c_walk(args->u[0].child, indent + IndentInc, 0);
  944.                prt_str(";", indent);
  945.                chkabsret(t, TypStr); /* compare return with abstract return */
  946.                return;
  947.             case Cset:
  948.                /*
  949.                 * return/suspend cset(<block-pntr>);
  950.                 */
  951.                ret_blk(t, args, "cset(bp)", "D_Cset", indent);
  952.                chkabsret(t, TypCset); /* compare return with abstract return */
  953.                return;
  954.             case Real:
  955.                /*
  956.                 * return/suspend real(<block-pntr>);
  957.                 */
  958.                ret_blk(t, args, "real(bp)", "D_Real", indent);
  959.                chkabsret(t, TypReal); /* compare return with abstract return */
  960.                return;
  961.             case File:
  962.                /*
  963.                 * return/suspend file(<block-pntr>);
  964.                 */
  965.                ret_blk(t, args, "file(bp)", "D_File", indent);
  966.                chkabsret(t, TypFile); /* compare return with abstract return */
  967.                return;
  968.             case Procedure:
  969.                /*
  970.                 * return/suspend prodecure(<block-pntr>);
  971.                 */
  972.                ret_blk(t, args, "procedure(bp)", "D_Proc", indent);
  973.                chkabsret(t, TypProc); /* compare return with abstract return */
  974.                return;
  975.             case List:
  976.                /*
  977.                 * return/suspend list(<block-pntr>);
  978.                 */
  979.                ret_blk(t, args, "list(bp)", "D_List", indent);
  980.                chkabsret(t, TypList); /* compare return with abstract return */
  981.                return;
  982.             case Set:
  983.                /*
  984.                 * return/suspend set(<block-pntr>);
  985.                 */
  986.                ret_blk(t, args, "set(bp)", "D_Set", indent);
  987.                chkabsret(t, TypSet); /* compare return with abstract return */
  988.                return;
  989.             case Record:
  990.                /*
  991.                 * return/suspend record(<block-pntr>);
  992.                 */
  993.                ret_blk(t, args, "record(bp)", "D_Record", indent);
  994.                chkabsret(t, TypRec); /* compare return with abstract return */
  995.                return;
  996.             case Table:
  997.                /*
  998.                 * return/suspend table(<block-pntr>);
  999.                 */
  1000.                ret_blk(t, args, "table(bp)", "D_Table", indent);
  1001.                chkabsret(t, TypTbl); /* compare return with abstract return */
  1002.                return;
  1003.             case Kywdint:
  1004.                /*
  1005.                 * return/suspend kwdint(<desc-pntr>);
  1006.                 */
  1007.                prt_str("VarLoc(", indent);
  1008.                prt_str(rslt_loc, indent);
  1009.                prt_str(") = ", indent);
  1010.                c_walk(args, indent + IndentInc, 0);
  1011.                prt_str(";", indent);
  1012.                ForceNl();
  1013.                prt_str(rslt_loc, indent);
  1014.                prt_str(".dword = D_Kywdint;", indent);
  1015.                chkabsret(t, TypKyInt); /* compare return with abstract return */
  1016.                return;
  1017.             case Kywdpos:
  1018.                /*
  1019.                 * return/suspend kwdpos(<desc-pntr>);
  1020.                 */
  1021.                prt_str("VarLoc(", indent);
  1022.                prt_str(rslt_loc, indent);
  1023.                prt_str(") = ", indent);
  1024.                c_walk(args, indent + IndentInc, 0);
  1025.                prt_str(";", indent);
  1026.                ForceNl();
  1027.                prt_str(rslt_loc, indent);
  1028.                prt_str(".dword = D_Kywdpos;", indent);
  1029.                chkabsret(t, TypKyPos); /* compare return with abstract return */
  1030.                return;
  1031.             case Kywdsubj:
  1032.                /*
  1033.                 * return/suspend kwdsubj(<desc-pntr>);
  1034.                 */
  1035.                prt_str("VarLoc(", indent);
  1036.                prt_str(rslt_loc, indent);
  1037.                prt_str(") = ", indent);
  1038.                c_walk(args, indent + IndentInc, 0);
  1039.                prt_str(";", indent);
  1040.                ForceNl();
  1041.                prt_str(rslt_loc, indent);
  1042.                prt_str(".dword = D_Kywdsubj;", indent);
  1043.                chkabsret(t, TypKySub); /* compare return with abstract return */
  1044.                return;
  1045.             case Tvtbl:
  1046.                /*
  1047.                 * return/suspend tvtbl(<block-pntr>);
  1048.                 */
  1049.                ret_blk(t, args, "tvtbl(bp)", "D_Tvtbl", indent);
  1050.                chkabsret(t, TypTvTbl); /* compare return with abstract return */
  1051.                return;
  1052.             case Co_expression:
  1053.                /*
  1054.                 * return/suspend co_expression(<stack-pntr>);
  1055.                 */
  1056.                ret_blk(t, args, "co_expression(bp)", "D_Coexpr", indent);
  1057.                chkabsret(t, TypCoExp); /* compare return with abstract return */
  1058.                return;
  1059.             case Named_var:
  1060.                /*
  1061.                 * return/suspend named_var(<desc-pntr>);
  1062.                 */
  1063.                if (args == NULL || args->nd_id == CommaNd)
  1064.                   errt1(t, "wrong no. of args for named_var(bp)");
  1065.                prt_str(rslt_loc, indent);
  1066.                prt_str(".vword.descptr = ", indent);
  1067.                c_walk(args, indent + IndentInc, 0);
  1068.                prt_str(";", indent);
  1069.                ForceNl();
  1070.                prt_str(rslt_loc, indent);
  1071.                prt_str(".dword = D_Var;", indent);
  1072.                chkabsret(t, TypVar); /* compare return with abstract return */
  1073.                return;
  1074.             case Struct_var:
  1075.                /*
  1076.                 * return/suspend struct_var(<desc-pntr>, <block_pntr>);
  1077.                 */
  1078.                if (args == NULL || args->nd_id != CommaNd ||
  1079.                   args->u[0].child->nd_id == CommaNd)
  1080.                   errt1(t, "wrong no. of args for struct_var(dp, bp)");
  1081.                prt_str(rslt_loc, indent);
  1082.                prt_str(".vword.descptr = (dptr)", indent);
  1083.                c_walk(args->u[1].child, indent + IndentInc, 0);
  1084.                prt_str(";", indent);
  1085.                ForceNl();
  1086.                prt_str(rslt_loc, indent);
  1087.                prt_str(".dword = D_Var + ((word *)", indent);
  1088.                c_walk(args->u[0].child, indent + IndentInc, 0);
  1089.                prt_str(" - (word *)", indent+IndentInc);
  1090.                prt_str(rslt_loc, indent);
  1091.                prt_str(".vword.descptr);", indent+IndentInc);
  1092.                ForceNl();
  1093.                chkabsret(t, TypVar); /* compare return with abstract return */
  1094.                return;
  1095.             case Substr:
  1096.                /*
  1097.                 * return/suspend substr(<desc-pntr>, <start>, <len>);
  1098.                 */
  1099.                if (args == NULL || args->nd_id != CommaNd ||
  1100.                   args->u[0].child->nd_id != CommaNd ||
  1101.                   args->u[0].child->u[0].child->nd_id == CommaNd)
  1102.                   errt1(t, "wrong no. of args for substr(dp, i, j)");
  1103.                no_nl = 1;
  1104.                prt_str("SubStr(&", indent);
  1105.                prt_str(rslt_loc, indent);
  1106.                prt_str(", ", indent);
  1107.                c_walk(args->u[0].child->u[0].child, indent + IndentInc, 0);
  1108.                prt_str(", ", indent + IndentInc);
  1109.                c_walk(args->u[1].child, indent + IndentInc, 0);
  1110.                prt_str(", ", indent + IndentInc);
  1111.                c_walk(args->u[0].child->u[1].child, indent + IndentInc, 0);
  1112.                prt_str(");", indent + IndentInc);
  1113.                no_nl = 0;
  1114.                /*
  1115.                 * The allocation of the substring trapped variable block
  1116.                 *   may fail.
  1117.                 */
  1118.                chk_rsltblk(indent);
  1119.                chkabsret(t, TypTvStr); /* compare return with abstract return */
  1120.                return;
  1121.             }
  1122.          }
  1123.       }
  1124.  
  1125.    /*
  1126.     * If it is not one of the special returns, it is just a return of
  1127.     *  a descriptor.
  1128.     */
  1129.    prt_str(rslt_loc, indent);
  1130.    prt_str(" = ", indent);
  1131.    c_walk(n, indent + IndentInc, 0);
  1132.    prt_str(";", indent);
  1133.    chkabsret(t, SomeType); /* check for preceding abstract return */
  1134.    }
  1135.  
  1136. /*
  1137.  * chk_rsltblk - the result value contains an allocated block, make sure
  1138.  *    the allocation succeeded.
  1139.  */
  1140. static novalue chk_rsltblk(indent)
  1141. int indent;
  1142.    {
  1143.    ForceNl();
  1144.    prt_str("if (", indent);
  1145.    prt_str(rslt_loc, indent);
  1146.    prt_str(".vword.bptr == NULL) {", indent);
  1147.    ForceNl();
  1148.    prt_str("err_msg(307, NULL);", indent + IndentInc);
  1149.    ForceNl();
  1150.    /*
  1151.     * Handle error conversion. Indicate that operation may fail because
  1152.     *  of error conversion and produce the necessary code.
  1153.     */
  1154.    cur_impl->ret_flag |= DoesEFail;
  1155.    failure(indent + IndentInc, 1);
  1156.    prt_str("}", indent + IndentInc);
  1157.    ForceNl();
  1158.    }
  1159.  
  1160. /*
  1161.  * ret_blk - produce code for a return/suspend that constructs a
  1162.  *  descriptor from a block pointer.
  1163.  */
  1164. static novalue ret_blk(t, args, constr, b_type, indent)
  1165. struct token *t;
  1166. struct node *args;
  1167. char *constr;
  1168. char *b_type;
  1169. int indent;
  1170.    {
  1171.    if (args == NULL || args->nd_id == CommaNd)
  1172.       errt2(t, "wrong no. of args for", constr);
  1173.    prt_str(rslt_loc, indent);
  1174.    prt_str(".vword.bptr = (union block *)", indent);
  1175.    c_walk(args, indent + IndentInc, 0);   /* block pointer */
  1176.    prt_str(";", indent);
  1177.    ForceNl();
  1178.    prt_str(rslt_loc, indent);
  1179.    prt_str(".dword = ", indent);
  1180.    prt_str(b_type, indent);               /* type code */
  1181.    prt_str(";", indent);
  1182.    }
  1183.  
  1184. /*
  1185.  * failure - produce code for fail or efail.
  1186.  */
  1187. static novalue failure(indent, brace)
  1188. int indent;
  1189. int brace;
  1190.    {
  1191.    /*
  1192.     * If there are tended variables, they must be removed from the tended
  1193.     *  list. The C function may or may not return an explicit signal.
  1194.     */
  1195.    ForceNl();
  1196.    if (ntend != 0) {
  1197.       if (!brace)
  1198.          prt_str("{", indent);
  1199.       untend(indent);
  1200.       ForceNl();
  1201.       if (fnc_ret == RetSig)
  1202.          prt_str("return A_Resume;", indent);
  1203.       else
  1204.          prt_str("return;", indent);
  1205.       if (!brace) {
  1206.          ForceNl();
  1207.          prt_str("}", indent);
  1208.          }
  1209.       }
  1210.    else
  1211.       if (fnc_ret == RetSig)
  1212.          prt_str("return A_Resume;", indent);
  1213.       else
  1214.          prt_str("return;", indent);
  1215.    ForceNl();
  1216.    }
  1217.  
  1218. /*
  1219.  * c_walk - walk the syntax tree for extended C code and output the
  1220.  *  corresponding ordinary C.
  1221.  */
  1222. novalue c_walk(n, indent, brace)
  1223. struct node *n;
  1224. int indent;
  1225. int brace;
  1226.    {
  1227.    struct token *t;
  1228.    struct node *n1;
  1229.    struct sym_entry *sym;
  1230.  
  1231.    if (n == NULL)
  1232.       return;
  1233.  
  1234.    t =  n->tok;
  1235.  
  1236.    switch (n->nd_id) {
  1237.       case PrimryNd:
  1238.          switch (t->tok_id) {
  1239.             case Fail:
  1240.                if (op_type == OrdFunc)
  1241.                   errt1(t, "'fail' may not be used in an ordinary C function");
  1242.                cur_impl->ret_flag |= DoesFail;
  1243.                failure(indent, brace);
  1244.            chkabsret(t, SomeType);  /* check preceding abstract return */
  1245.            break;
  1246.         case Errorfail:
  1247.            if (op_type == OrdFunc)
  1248.           errt1(t,
  1249.               "'errorfail' may not be used in an ordinary C function");
  1250.            cur_impl->ret_flag |= DoesEFail;
  1251.            failure(indent, brace);
  1252.            break;
  1253.         default:
  1254.                /*
  1255.                 * Other "primary" expressions are just their token image,
  1256.                 *  possibly followed by a semicolon.
  1257.                 */
  1258.            prt_tok(t, indent);
  1259.            if (t->tok_id == Break || t->tok_id == Continue)
  1260.           prt_str(";", indent);
  1261.         }
  1262.      break;
  1263.       case PrefxNd:
  1264.      switch (t->tok_id) {
  1265.         case Sizeof:
  1266.            prt_tok(t, indent);                /* sizeof */
  1267.            prt_str("(", indent);
  1268.            c_walk(n->u[0].child, indent, 0);
  1269.            prt_str(")", indent);
  1270.            break;
  1271.         case '{':
  1272.                /*
  1273.                 * Initailizer list.
  1274.                 */
  1275.            prt_tok(t, indent + IndentInc);     /* { */
  1276.            c_walk(n->u[0].child, indent + IndentInc, 0);
  1277.            prt_str("}", indent + IndentInc);
  1278.            break;
  1279.         case Default:
  1280.            prt_tok(t, indent - IndentInc);     /* default (un-indented) */
  1281.            prt_str(": ", indent - IndentInc);
  1282.            c_walk(n->u[0].child, indent, 0);
  1283.            break;
  1284.         case Goto:
  1285.            prt_tok(t, indent);                 /* goto */
  1286.            prt_str(" ", indent);
  1287.            c_walk(n->u[0].child, indent, 0);
  1288.            prt_str(";", indent);
  1289.            break;
  1290.         case Return:
  1291.            if (n->u[0].child != NULL)
  1292.           no_ret_val = 0;  /* note that return statement has no value */
  1293.  
  1294.            if (op_type == OrdFunc || fnc_ret == RetInt ||
  1295.           fnc_ret == RetDbl) {
  1296.           /*
  1297.            * ordinary C return: ignore C_integer, C_double, and
  1298.            *  C_string qualifiers on return expression (the first
  1299.            *  two may legally occur when fnc_ret is RetInt or RetDbl).
  1300.            */
  1301.           n1 = n->u[0].child;
  1302.           if (n1 != NULL && n1->nd_id == PrefxNd && n1->tok != NULL) {
  1303.              switch (n1->tok->tok_id) {
  1304.             case C_Integer:
  1305.             case C_Double:
  1306.             case C_String:
  1307.                n1 = n1->u[0].child;
  1308.             }
  1309.              }
  1310.           if (ntend != 0) {
  1311.                      /*
  1312.                       * There are tended variables that must be removed from
  1313.                       *  the tended list.
  1314.                       */
  1315.              if (!brace)
  1316.             prt_str("{", indent);
  1317.              if (does_call(n1)) {
  1318.             /*
  1319.              * The return expression contains a function call;
  1320.                          *  the variables must remain tended while it is
  1321.                          *  computed, so compute it into a temporary variable
  1322.                          *  named r_retval.Output a declaration for r_retval;
  1323.                          *  its type must match the return type of the C
  1324.                          *  function.
  1325.                          */
  1326.             ForceNl();
  1327.             prt_str("register ", indent);
  1328.             if (op_type == OrdFunc) {
  1329.                no_nl = 1;
  1330.                just_type(fnc_head->u[0].child, indent, 0);
  1331.                prt_str(" ", indent);
  1332.                retval_dcltor(fnc_head->u[1].child, indent);
  1333.                prt_str(";", indent);
  1334.                no_nl = 0;
  1335.                }
  1336.             else if (fnc_ret == RetInt)
  1337.                prt_str("C_integer r_retval;", indent);
  1338.             else    /* fnc_ret == RetDbl */
  1339.                prt_str("double r_retval;", indent);
  1340.             ForceNl();
  1341.  
  1342.                         /*
  1343.                          * Output code to compute the return value, untend
  1344.                          *  the variable, then return the value.
  1345.                          */
  1346.             prt_str("r_retval = ", indent);
  1347.             c_walk(n1, indent + IndentInc, 0);
  1348.             prt_str(";", indent);
  1349.             untend(indent);
  1350.             ForceNl();
  1351.             prt_str("return r_retval;", indent);
  1352.             }
  1353.              else {
  1354.                         /*
  1355.                          * It is safe to untend the variables and return
  1356.                          *  the result value directly with a return
  1357.                          *  statement.
  1358.                          */
  1359.             untend(indent);
  1360.             ForceNl();
  1361.             prt_tok(t, indent);    /* return */
  1362.             prt_str(" ", indent);
  1363.             c_walk(n1, indent, 0);
  1364.             prt_str(";", indent);
  1365.             }
  1366.              if (!brace) {
  1367.             ForceNl();
  1368.             prt_str("}", indent);
  1369.             }
  1370.              ForceNl();
  1371.              }
  1372.           else {
  1373.                      /*
  1374.                       * There are no tended variable, just output the
  1375.                       *  return expression.
  1376.                       */
  1377.              prt_tok(t, indent);     /* return */
  1378.              prt_str(" ", indent);
  1379.              c_walk(n1, indent, 0);
  1380.              prt_str(";", indent);
  1381.              }
  1382.  
  1383.                   /*
  1384.                    * If this is a body function, check the return against
  1385.                    *  preceding abstract returns.
  1386.                    */
  1387.           if (fnc_ret == RetInt)
  1388.              chkabsret(n->tok, TypInt);
  1389.                   else if (fnc_ret == RetDbl)
  1390.                      chkabsret(n->tok, TypReal);
  1391.                   }
  1392.                else {
  1393.                   /*
  1394.                    * Return from Icon operation. Indicate that the operation
  1395.                    *  returns, compute the value into the result location,
  1396.                    *  untend variables if necessary, and return a signal
  1397.                    *  if the function requires one.
  1398.                    */
  1399.                   cur_impl->ret_flag |= DoesRet;
  1400.                   ForceNl();
  1401.                   if (!brace) {
  1402.                      prt_str("{", indent);
  1403.                      ForceNl();
  1404.                      }
  1405.                   ret_value(t, n->u[0].child, indent);
  1406.                   if (ntend != 0)
  1407.                      untend(indent);
  1408.                   ForceNl();
  1409.                   if (fnc_ret == RetSig)
  1410.                      prt_str("return A_Continue;", indent);
  1411.                   else if (fnc_ret == RetNoVal)
  1412.                      prt_str("return;", indent);
  1413.                   ForceNl();
  1414.                   if (!brace) {
  1415.                      prt_str("}", indent);
  1416.                      ForceNl();
  1417.                      }
  1418.                   }
  1419.                break;
  1420.             case Suspend:
  1421.                if (op_type == OrdFunc)
  1422.                   errt1(t, "'suspend' may not be used in an ordinary C function"
  1423.                      );
  1424.                cur_impl->ret_flag |= DoesSusp; /* note suspension */
  1425.                ForceNl();
  1426.                if (!brace) {
  1427.                   prt_str("{", indent);
  1428.                   ForceNl();
  1429.                   }
  1430.                prt_str("register int signal;", indent + IndentInc);
  1431.                ForceNl();
  1432.                ret_value(t, n->u[0].child, indent);
  1433.                ForceNl();
  1434.                /*
  1435.                 * The operator suspends by calling the success continuation
  1436.                 *  if there is one or just returns if there is none. For
  1437.                 *  the interpreter, interp() is the success continuation.
  1438.                 *  A non-A_Resume signal from the success continuation must
  1439.                 *  returned to the caller. If there are tended variables
  1440.                 *  they must be removed from the tended list before a signal
  1441.                 *  is returned.
  1442.                 */
  1443.                if (iconx_flg)
  1444.                   prt_str(
  1445.                      "if ((signal = interp(G_Csusp, r_args)) != A_Resume) {",
  1446.                      indent);
  1447.                else {
  1448.                   prt_str("if (r_s_cont == (continuation)NULL) {", indent);
  1449.                   if (ntend != 0)
  1450.                      untend(indent + IndentInc);
  1451.                   ForceNl();
  1452.                   prt_str("return A_Continue;", indent + IndentInc);
  1453.                   ForceNl();
  1454.                   prt_str("}", indent + IndentInc);
  1455.                   ForceNl();
  1456.                   prt_str("else if ((signal = (*r_s_cont)()) != A_Resume) {",
  1457.                      indent);
  1458.                   }
  1459.                ForceNl();
  1460.                if (ntend != 0)
  1461.                   untend(indent + IndentInc);
  1462.                ForceNl();
  1463.                prt_str("return signal;", indent + IndentInc);
  1464.                ForceNl();
  1465.                prt_str("}", indent + IndentInc);
  1466.                if (!brace) {
  1467.                   prt_str("}", indent);
  1468.                   ForceNl();
  1469.                   }
  1470.                break;
  1471.             case '(':
  1472.                /*
  1473.                 * Parenthesized expression.
  1474.                 */
  1475.                prt_tok(t, indent);     /* ( */
  1476.                c_walk(n->u[0].child, indent, 0);
  1477.                prt_str(")", indent);
  1478.                break;
  1479.             default:
  1480.                /*
  1481.                 * All other prefix expressions are printed as the token
  1482.                 *  image of the operation followed by the operand.
  1483.                 */
  1484.                prt_tok(t, indent);
  1485.                c_walk(n->u[0].child, indent, 0);
  1486.             }
  1487.          break;
  1488.       case PstfxNd:
  1489.          /*
  1490.           * All postfix expressions are printed as the operand followed
  1491.           *  by the token image of the operation.
  1492.           */
  1493.          c_walk(n->u[0].child, indent, 0);
  1494.          prt_tok(t, indent);
  1495.          break;
  1496.       case PreSpcNd:
  1497.          /*
  1498.           * This prefix expression (pointer indication in a declaration) needs
  1499.           *  a space after it.
  1500.           */
  1501.          prt_tok(t, indent);
  1502.          c_walk(n->u[0].child, indent, 0);
  1503.          prt_str(" ", indent);
  1504.          break;
  1505.       case SymNd:
  1506.          /*
  1507.           * Identifier.
  1508.           */
  1509.          prt_var(n, indent);
  1510.          break;
  1511.       case BinryNd:
  1512.          switch (t->tok_id) {
  1513.             case '[':
  1514.                /*
  1515.                 * subsrcipting expression or declaration: <expr> [ <expr> ]
  1516.                 */
  1517.                n1 = n->u[0].child;
  1518.                c_walk(n->u[0].child, indent, 0);
  1519.                prt_str("[", indent);
  1520.                c_walk(n->u[1].child, indent, 0);
  1521.                prt_str("]", indent);
  1522.                break;
  1523.             case '(':
  1524.                /*
  1525.                 * cast: ( <type> ) <expr>
  1526.                 */
  1527.                prt_tok(t, indent);  /* ) */
  1528.                c_walk(n->u[0].child, indent, 0);
  1529.                prt_str(")", indent);
  1530.                c_walk(n->u[1].child, indent, 0);
  1531.                break;
  1532.             case ')':
  1533.                /*
  1534.                 * function call or declaration: <expr> ( <expr-list> )
  1535.                 */
  1536.                c_walk(n->u[0].child, indent, 0);
  1537.                prt_str("(", indent);
  1538.                c_walk(n->u[1].child, indent, 0);
  1539.                prt_tok(t, indent);   /* ) */
  1540.                break;
  1541.             case Struct:
  1542.             case Union:
  1543.                /*
  1544.                 * struct/union <ident>
  1545.                 * struct/union <opt-ident> { <field-list> }
  1546.                 */
  1547.                prt_tok(t, indent);   /* struct or union */
  1548.                prt_str(" ", indent);
  1549.                c_walk(n->u[0].child, indent, 0);
  1550.                if (n->u[1].child != NULL) {
  1551.                   /*
  1552.                    * Field declaration list.
  1553.                    */
  1554.                   prt_str(" {", indent);
  1555.                   c_walk(n->u[1].child, indent + IndentInc, 0);
  1556.                   ForceNl();
  1557.                   prt_str("}", indent);
  1558.                   }
  1559.                break;
  1560.             case Enum:
  1561.                /*
  1562.                 * enum <ident>
  1563.                 * enum <opt-ident> { <enum-list> }
  1564.                 */
  1565.                prt_tok(t, indent);   /* enum */
  1566.                prt_str(" ", indent);
  1567.                c_walk(n->u[0].child, indent, 0);
  1568.                if (n->u[1].child != NULL) {
  1569.                   /*
  1570.                    * enumerator list.
  1571.                    */
  1572.                   prt_str(" {", indent);
  1573.                   c_walk(n->u[1].child, indent + IndentInc, 0);
  1574.                   prt_str("}", indent);
  1575.                   }
  1576.                break;
  1577.             case ';':
  1578.                /*
  1579.                 * <type-specs> <declarator> ;
  1580.                 */
  1581.                c_walk(n->u[0].child, indent, 0);
  1582.                prt_str(" ", indent);
  1583.                c_walk(n->u[1].child, indent, 0);
  1584.                prt_tok(t, indent);  /* ; */
  1585.                break;
  1586.             case ':':
  1587.                /*
  1588.                 * <label> : <statement>
  1589.                 */
  1590.                c_walk(n->u[0].child, indent, 0);
  1591.                prt_tok(t, indent);   /* : */
  1592.                prt_str(" ", indent);
  1593.                c_walk(n->u[1].child, indent, 0);
  1594.                break;
  1595.             case Case:
  1596.                /*
  1597.                 * case <expr> : <statement>
  1598.                 */
  1599.                prt_tok(t, indent - IndentInc);  /* case (un-indented) */
  1600.                prt_str(" ", indent);
  1601.                c_walk(n->u[0].child, indent - IndentInc, 0);
  1602.                prt_str(": ", indent - IndentInc);
  1603.                c_walk(n->u[1].child, indent, 0);
  1604.                break;
  1605.             case Switch:
  1606.                /*
  1607.                 * switch ( <expr> ) <statement>
  1608.                 *
  1609.                 * <statement> is double indented so that case and default
  1610.                 * statements can be un-indented and come out indented 1
  1611.                 * with respect to the switch. Statement that are not
  1612.                 * "labeled" with case or default are indented one more
  1613.                 * than those that are labeled.
  1614.                 */
  1615.                prt_tok(t, indent);  /* switch */
  1616.                prt_str(" (", indent);
  1617.                c_walk(n->u[0].child, indent, 0);
  1618.                prt_str(")", indent);
  1619.                prt_str(" ", indent);
  1620.                c_walk(n->u[1].child, indent + 2 * IndentInc, 0);
  1621.                break;
  1622.             case While:
  1623.                /*
  1624.                 * While ( <expr> ) <statement>
  1625.                 */
  1626.                prt_tok(t, indent);  /* while */
  1627.                prt_str(" (", indent);
  1628.                c_walk(n->u[0].child, indent, 0);
  1629.                prt_str(")", indent);
  1630.                prt_str(" ", indent);
  1631.                c_walk(n->u[1].child, indent + IndentInc, 0);
  1632.                break;
  1633.             case Do:
  1634.                /*
  1635.                 * do <statement> <while> ( <expr> )
  1636.                 */
  1637.                prt_tok(t, indent);  /* do */
  1638.                prt_str(" ", indent);
  1639.                c_walk(n->u[0].child, indent + IndentInc, 0);
  1640.                ForceNl();
  1641.                prt_str("while (", indent);
  1642.                c_walk(n->u[1].child, indent, 0);
  1643.                prt_str(");", indent);
  1644.                break;
  1645.             case '.':
  1646.             case Arrow:
  1647.                /*
  1648.                 * Field access: <expr> . <expr>  and  <expr> -> <expr>
  1649.                 */
  1650.                c_walk(n->u[0].child, indent, 0);
  1651.                prt_tok(t, indent);   /* . or -> */
  1652.                c_walk(n->u[1].child, indent, 0);
  1653.                break;
  1654.             case Runerr:
  1655.                /*
  1656.                 * runerr ( <error-number> )
  1657.                 * runerr ( <error-number> , <offending-value> )
  1658.                 */
  1659.                prt_runerr(n, indent);
  1660.                break;
  1661.             case Is:
  1662.                /*
  1663.                 * is : <type> ( <expr> )
  1664.                 */
  1665.                typ_asrt(n->u[0].child->tok, n->u[1].child, indent);
  1666.                break;
  1667.             default:
  1668.                /*
  1669.                 * All other binary expressions are infix notaton and
  1670.                 *  are printed with spaces around the operator.
  1671.                 */
  1672.                c_walk(n->u[0].child, indent, 0);
  1673.                prt_str(" ", indent);
  1674.                prt_tok(t, indent);
  1675.                prt_str(" ", indent);
  1676.                c_walk(n->u[1].child, indent, 0);
  1677.                break;
  1678.             }
  1679.          break;
  1680.       case LstNd:
  1681.          /*
  1682.           * <declaration-part> <declaration-part>
  1683.           *
  1684.           * Need space between parts
  1685.           */
  1686.          c_walk(n->u[0].child, indent, 0);
  1687.          prt_str(" ", indent);
  1688.          c_walk(n->u[1].child, indent, 0);
  1689.          break;
  1690.       case ConCatNd:
  1691.          /*
  1692.           * <some-code> <some-code>
  1693.           *
  1694.           * Various lists of code parts that do not need space between them.
  1695.           */
  1696.          c_walk(n->u[0].child, indent, 0);
  1697.          c_walk(n->u[1].child, indent, 0);
  1698.          break;
  1699.       case CommaNd:
  1700.          /*
  1701.           * <expr> , <expr>
  1702.           */
  1703.          c_walk(n->u[0].child, indent, 0);
  1704.          prt_tok(t, indent);
  1705.          prt_str(" ", indent);
  1706.          c_walk(n->u[1].child, indent, 0);
  1707.          break;
  1708.       case StrDclNd:
  1709.          /*
  1710.           * Structure field declaration. Bit field declarations have
  1711.           *  a semicolon and a field width.
  1712.           */
  1713.          c_walk(n->u[0].child, indent, 0);
  1714.          if (n->u[1].child != NULL) {
  1715.             prt_str(": ", indent);
  1716.             c_walk(n->u[1].child, indent, 0);
  1717.             }
  1718.          break;
  1719.       case CompNd:
  1720.          /*
  1721.           * Compound statement.
  1722.           */
  1723.          if (brace)
  1724.             tok_line(t, indent); /* just synch. file name and line number */
  1725.          else
  1726.             prt_tok(t, indent);  /* { */
  1727.          c_walk(n->u[0].child, indent, 0);
  1728.          /*
  1729.           * we are in an inner block. tended locations may need to
  1730.           *  be set to values from declaration initializations.
  1731.           */
  1732.          for (sym = n->u[1].sym; sym!= NULL; sym = sym->u.tnd_var.next) {
  1733.             if (sym->u.tnd_var.init != NULL) {
  1734.                prt_str(tendstrct, IndentInc);
  1735.                fprintf(out_file, ".d[%d]", sym->t_indx);
  1736.                switch (sym->id_type) {
  1737.                   case TndDesc:
  1738.                      prt_str(" = ", IndentInc);
  1739.                      break;
  1740.                   case TndStr:
  1741.                      prt_str(".vword.sptr = ", IndentInc);
  1742.                      break;
  1743.                   case TndBlk:
  1744.                      prt_str(".vword.bptr = (union block *)",
  1745.                         IndentInc);
  1746.                      break;
  1747.                   }
  1748.                c_walk(sym->u.tnd_var.init, 2 * IndentInc, 0);
  1749.                prt_str(";", 2 * IndentInc);
  1750.                ForceNl();
  1751.                }
  1752.             }
  1753.          /*
  1754.           * If there are no declarations, suppress braces that
  1755.           *  may be required for a one-statement body; we already
  1756.           *  have a set.
  1757.           */
  1758.          if (n->u[0].child == NULL && n->u[1].sym == NULL)
  1759.             c_walk(n->u[2].child, indent, 1);
  1760.          else
  1761.             c_walk(n->u[2].child, indent, 0);
  1762.          if (!brace) {
  1763.             ForceNl();
  1764.             prt_str("}", indent);
  1765.             }
  1766.          break;
  1767.       case TrnryNd:
  1768.          switch (t->tok_id) {
  1769.             case '?':
  1770.                /*
  1771.                 * <expr> ? <expr> : <expr>
  1772.                 */
  1773.                c_walk(n->u[0].child, indent, 0);
  1774.                prt_str(" ", indent);
  1775.                prt_tok(t, indent);  /* ? */
  1776.                prt_str(" ", indent);
  1777.                c_walk(n->u[1].child, indent, 0);
  1778.                prt_str(" : ", indent);
  1779.                c_walk(n->u[2].child, indent, 0);
  1780.                break;
  1781.             case If:
  1782.                /*
  1783.                 * if ( <expr> ) <statement>
  1784.                 * if ( <expr> ) <statement> else <statement>
  1785.                 */
  1786.                prt_tok(t, indent);  /* then */
  1787.                prt_str(" (", indent);
  1788.                c_walk(n->u[0].child, indent + IndentInc, 0);
  1789.                prt_str(") ", indent);
  1790.                c_walk(n->u[1].child, indent + IndentInc, 0);
  1791.                n1 = n->u[2].child;
  1792.                if (n1 != NULL) {
  1793.                   /*
  1794.                    * There is an else statement. Don't indent an
  1795.                    *  "else if"
  1796.                    */
  1797.                   ForceNl();
  1798.                   prt_str("else ", indent);
  1799.                   if (n1->nd_id == TrnryNd && n1->tok->tok_id == If)
  1800.                      c_walk(n1, indent, 0);
  1801.                   else
  1802.                      c_walk(n1, indent + IndentInc, 0);
  1803.                   }
  1804.                break;
  1805.             case Type_case:
  1806.                /*
  1807.                 * type_case <expr> of { <section-list> }
  1808.                 * type_case <expr> of { <section-list> <default-clause> }
  1809.                 */
  1810.                typ_case(n->u[0].child, n->u[1].child, n->u[2].child, c_walk,
  1811.                   1, indent);
  1812.                break;
  1813.             case Cnv:
  1814.                /*
  1815.                 * cnv : <type> ( <source> , <destination> )
  1816.                 */
  1817.                cnv_fnc(t, n->u[0].child, n->u[1].child, NULL, n->u[2].child,
  1818.                   indent);
  1819.                break;
  1820.             }
  1821.          break;
  1822.       case QuadNd:
  1823.          switch (t->tok_id) {
  1824.             case For:
  1825.                /*
  1826.                 * for ( <expr> ; <expr> ; <expr> ) <statement>
  1827.                 */
  1828.                prt_tok(t, indent);  /* for */
  1829.                prt_str(" (", indent);
  1830.                c_walk(n->u[0].child, indent, 0);
  1831.                prt_str("; ", indent);
  1832.                c_walk(n->u[1].child, indent, 0);
  1833.                prt_str("; ", indent);
  1834.                c_walk(n->u[2].child, indent, 0);
  1835.                prt_str(") ", indent);
  1836.                c_walk(n->u[3].child, indent + IndentInc, 0);
  1837.                break;
  1838.             case Def:
  1839.                /*
  1840.                 * def : <type> ( <source> , <default> , <destination> )
  1841.                 */
  1842.                cnv_fnc(t, n->u[0].child, n->u[1].child, n->u[2].child,
  1843.                   n->u[3].child, indent);
  1844.                break;
  1845.             }
  1846.          break;
  1847.       }
  1848.    }
  1849.  
  1850. /*
  1851.  * new_prmloc - allocate an array large enough to hold a flag for every
  1852.  *  parameter of the current operation. This flag indicates where
  1853.  *  the parameter is in terms of scopes created by conversions.
  1854.  */
  1855. int *new_prmloc()
  1856.    {
  1857.    int *prmlocs;
  1858.    int nparams;
  1859.    int i;
  1860.  
  1861.    if (params == NULL)
  1862.       return NULL;
  1863.    nparams = params->u.param_info.param_num + 1;
  1864.    prmlocs = (int *)alloc((unsigned)nparams * sizeof(int));
  1865.    for (i = 0; i < nparams; ++i)
  1866.       prmlocs[i] = 0;
  1867.    return prmlocs;
  1868.    }
  1869.  
  1870. /*
  1871.  * ld_prmloc - load parameter location information that has been
  1872.  *  saved in an arrary into the symbol table.
  1873.  */
  1874. novalue ld_prmloc(prmlocs)
  1875. int *prmlocs;
  1876.    {
  1877.    struct sym_entry *sym;
  1878.  
  1879.    for (sym = params; sym != NULL; sym = sym->u.param_info.next)
  1880.       if (sym->id_type & DrfPrm)
  1881.          sym->u.param_info.cur_loc = prmlocs[sym->u.param_info.param_num];
  1882.    }
  1883.  
  1884. /*
  1885.  * sv_prmloc - save parameter location information from the the symbol table
  1886.  *  into an array.
  1887.  */
  1888. novalue sv_prmloc(prmlocs)
  1889. int *prmlocs;
  1890.    {
  1891.    struct sym_entry *sym;
  1892.  
  1893.    for (sym = params; sym != NULL; sym = sym->u.param_info.next)
  1894.       if (sym->id_type & DrfPrm)
  1895.          prmlocs[sym->u.param_info.param_num] = sym->u.param_info.cur_loc;
  1896.    }
  1897.  
  1898. /*
  1899.  * mrg_prmloc - merge parameter location information in the symbol table
  1900.  *  with other information already saved in an array. This may result
  1901.  *  in conflicting location information, but conflicts are only detected
  1902.  *  when a parameter is actually used.
  1903.  */
  1904. novalue mrg_prmloc(prmlocs)
  1905. int *prmlocs;
  1906.    {
  1907.    struct sym_entry *sym;
  1908.  
  1909.    for (sym = params; sym != NULL; sym = sym->u.param_info.next)
  1910.       if (sym->id_type & DrfPrm)
  1911.          prmlocs[sym->u.param_info.param_num] |= sym->u.param_info.cur_loc;
  1912.    }
  1913.  
  1914. /*
  1915.  * typ_case - translate a type_case statement into C. This is called
  1916.  *  while walking a syntax tree of either RTL code or C code; the parameter
  1917.  *  "walk" is a function used to process the subtrees within the type_case
  1918.  *  statement.
  1919.  */
  1920. static novalue typ_case(var, slct_lst, dflt, walk, maybe_var, indent)
  1921. struct node *var;
  1922. struct node *slct_lst;
  1923. struct node *dflt;
  1924. novalue (*walk)();
  1925. int maybe_var;
  1926. int indent;
  1927.    {
  1928.    struct node *lst;
  1929.    struct node *select;
  1930.    struct node *slctor;
  1931.    int *strt_prms;
  1932.    int *end_prms;
  1933.    int remaining;
  1934.    int first;
  1935.    int fnd_slctrs;
  1936.    int maybe_str = 1;
  1937.    int dflt_lbl;
  1938.    struct token *typ;
  1939.    char *s;
  1940.  
  1941.    /*
  1942.     * This statement involves multiple paths that may establish new
  1943.     *  scopes for parameters. Remember the starting scope information
  1944.     *  and initialize an array in which to compute the final information.
  1945.     */
  1946.    strt_prms = new_prmloc();
  1947.    sv_prmloc(strt_prms);
  1948.    end_prms = new_prmloc();
  1949.  
  1950.    /*
  1951.     * First look for cases that must be checked with "if" statements.
  1952.     *  These include string qualifiers and variables.
  1953.     */
  1954.    remaining = 0;      /* number of cases skipped in first pass */
  1955.    first = 1;          /* next case to be output is the first */
  1956.    for (lst = slct_lst; lst != NULL; lst = lst->u[0].child) {
  1957.       select = lst->u[1].child;
  1958.       fnd_slctrs = 0; /* flag: found type selections for clause for this pass */
  1959.       /*
  1960.        * A selection clause may include several types. 
  1961.        */
  1962.       for (slctor = select->u[0].child; slctor != NULL; slctor =
  1963.         slctor->u[0].child) {
  1964.          if(typ_code(slctor->u[1].child->tok) == NULL) {
  1965.             /*
  1966.              * This type must be checked with the "if". Is this the
  1967.              *  first condition checked for this clause? Is this the
  1968.              *  first clause output?
  1969.              */
  1970.             if (fnd_slctrs)
  1971.                prt_str(" || ", indent);
  1972.             else {
  1973.                if (first)
  1974.                   first = 0;
  1975.                else {
  1976.                   ForceNl();
  1977.                   prt_str("else ", indent);
  1978.                   }
  1979.                prt_str("if (", indent);
  1980.                fnd_slctrs = 1;
  1981.                }
  1982.             typ = slctor->u[1].child->tok;
  1983.             typ_asrt(typ, var, indent + IndentInc); /* output type check */
  1984.             switch (typ->tok_id) {
  1985.                case String:
  1986.                   maybe_str = 0;  /* string has been taken care of */
  1987.                   break;
  1988.                case Variable:
  1989.                   maybe_var = 0;  /* variable has been taken care of */
  1990.                   break;
  1991.                   }
  1992.             }
  1993.          else
  1994.             ++remaining;
  1995.          }
  1996.       if (fnd_slctrs) {
  1997.          /*
  1998.           * We have found and output type selections for this clause;
  1999.           *  output the body of the clause. Remember any changes to
  2000.           *  paramter locations caused by type conversions within the
  2001.           *  clause.
  2002.           */
  2003.          prt_str(") {", indent + IndentInc);
  2004.          ForceNl();
  2005.          (*walk)(select->u[1].child, indent + IndentInc, 1);
  2006.          prt_str("}", indent + IndentInc);
  2007.          ForceNl();
  2008.          mrg_prmloc(end_prms);
  2009.          ld_prmloc(strt_prms);
  2010.          }
  2011.       }
  2012.    /*
  2013.     * The rest of the cases can be checked with a "switch" statement, look
  2014.     *  for them..
  2015.     */
  2016.    if (remaining == 0) {
  2017.       if (dflt != NULL) {
  2018.          /*
  2019.           * There are no cases to handle with a switch statement, but there
  2020.           *  is a default clause; handle it with an "else".
  2021.           */
  2022.          prt_str("else {", indent);
  2023.          ForceNl();
  2024.          (*walk)(dflt, indent + IndentInc, 1);
  2025.          ForceNl();
  2026.          prt_str("}", indent + IndentInc);
  2027.          ForceNl();
  2028.          }
  2029.       }
  2030.    else {
  2031.       /*
  2032.        * If an "if" statement was output, the "switch" must be in its "else"
  2033.        *   clause.
  2034.        */
  2035.       if (!first)
  2036.          prt_str("else ", indent);
  2037.  
  2038.       /*
  2039.        * A switch statement cannot handle types that are not simple type
  2040.        *  codes. If these have not taken care of, output code to check them.
  2041.        *  This will either branch around the switch statement or into
  2042.        *  its default clause.
  2043.        */
  2044.       if (maybe_str || maybe_var) {
  2045.          dflt_lbl = lbl_num++;      /* allocate a label number */
  2046.          prt_str("{", indent);
  2047.          ForceNl();
  2048.          prt_str("if (((", indent);
  2049.          c_walk(var, indent + IndentInc, 0);
  2050.          prt_str(").dword & D_Typecode) != D_Typecode) ", indent);
  2051.          ForceNl();
  2052.          prt_str("goto L", indent + IndentInc);
  2053.          fprintf(out_file, "%d;  /* default */ ", dflt_lbl);
  2054.          ForceNl();
  2055.          }
  2056.  
  2057.       no_nl = 1; /* suppress #line directives */
  2058.       prt_str("switch (Type(", indent);
  2059.       c_walk(var, indent + IndentInc, 0);
  2060.       prt_str(")) {", indent + IndentInc);
  2061.       no_nl = 0;
  2062.       ForceNl();
  2063.  
  2064.       /*
  2065.        * Loop through the case clauses looking producing code for them.
  2066.        */
  2067.       for (lst = slct_lst; lst != NULL; lst = lst->u[0].child) {
  2068.          select = lst->u[1].child;
  2069.          fnd_slctrs = 0;
  2070.          /*
  2071.           * A selection clause may include several types. 
  2072.           */
  2073.          for (slctor = select->u[0].child; slctor != NULL; slctor =
  2074.            slctor->u[0].child) {
  2075.             s = typ_code(slctor->u[1].child->tok);
  2076.             if (s != NULL) {
  2077.                /*
  2078.                 * A type selection has been found that can be checked
  2079.                 *  in the switch statement. Note that large integers
  2080.                 *  require special handling.
  2081.                 */
  2082.                fnd_slctrs = 1;
  2083.  
  2084.            if (!strcmp(s,"Integer")) {
  2085.          ForceNl();
  2086.          prt_str("#ifdef LargeInts", 0);
  2087.          ForceNl();
  2088.          prt_str("case T_Lrgint:  ", indent + IndentInc);
  2089.          ForceNl();
  2090.          prt_str("#endif /* LargeInts */", 0);
  2091.          ForceNl();
  2092.            }
  2093.  
  2094.                prt_str("case T_", indent + IndentInc);
  2095.                prt_str(s, indent + IndentInc);
  2096.                prt_str(": ", indent + IndentInc);
  2097.                }
  2098.             }
  2099.          if (fnd_slctrs) {
  2100.             /*
  2101.              * We have found and output type selections for this clause;
  2102.              *  output the body of the clause. Remember any changes to
  2103.              *  paramter locations caused by type conversions within the
  2104.              *  clause.
  2105.              */
  2106.             ForceNl();
  2107.             (*walk)(select->u[1].child, indent + 2 * IndentInc, 0);
  2108.             ForceNl();
  2109.             prt_str("break;", indent + 2 * IndentInc);
  2110.             ForceNl();
  2111.             mrg_prmloc(end_prms);
  2112.             ld_prmloc(strt_prms);
  2113.             }
  2114.          }
  2115.       if (dflt != NULL) {
  2116.          /*
  2117.           * This type_case statement has a default clause. If there is
  2118.           *  a branch into this clause, output the label. Remember any
  2119.           *  changes to paramter locations caused by type conversions
  2120.           *  within the clause.
  2121.           */
  2122.          ForceNl();
  2123.          prt_str("default:", indent + 1 * IndentInc);
  2124.          ForceNl();
  2125.          if (maybe_str || maybe_var) {
  2126.             prt_str("L", 0);
  2127.             fprintf(out_file, "%d: ;  /* default */", dflt_lbl);
  2128.             ForceNl();
  2129.             }
  2130.          (*walk)(dflt, indent + 2 * IndentInc, 0);
  2131.          ForceNl();
  2132.          mrg_prmloc(end_prms);
  2133.          ld_prmloc(strt_prms);
  2134.          }
  2135.       prt_str("}", indent + IndentInc);
  2136.  
  2137.       if (maybe_str || maybe_var) {
  2138.          if (dflt == NULL) {
  2139.             /*
  2140.              * There is a branch around the switch statement. Output
  2141.              *  the label.
  2142.              */
  2143.             ForceNl();
  2144.             prt_str("L", 0);
  2145.             fprintf(out_file, "%d: ;  /* default */", dflt_lbl);
  2146.             }
  2147.          ForceNl();
  2148.          prt_str("}", indent + IndentInc);
  2149.          }
  2150.       ForceNl();
  2151.       }
  2152.  
  2153.    /*
  2154.     * Put ending parameter locations into effect.
  2155.     */
  2156.    mrg_prmloc(end_prms);
  2157.    ld_prmloc(end_prms);
  2158.    if (strt_prms != NULL)
  2159.       free(strt_prms);
  2160.    if (end_prms != NULL)
  2161.       free(end_prms);
  2162.    }
  2163.  
  2164. /*
  2165.  * chk_conj - see if the left argument of a conjuction is an in-place
  2166.  *   conversion of a parameter other than a conversion to C_integer or
  2167.  *   C_double. If so issue a warning.
  2168.  */
  2169. static novalue chk_conj(n)
  2170. struct node *n;
  2171.    {
  2172.    struct node *cnv_type;
  2173.    struct node *src;
  2174.    struct node *dest;
  2175.  
  2176.    if (n->nd_id == BinryNd && n->tok->tok_id == And)
  2177.       n = n->u[1].child;
  2178.  
  2179.    switch (n->nd_id) {
  2180.       case TrnryNd:
  2181.          /*
  2182.           * Must be Cnv.
  2183.           */
  2184.          cnv_type = n->u[0].child;
  2185.          src = n->u[1].child;
  2186.          dest = n->u[2].child;
  2187.          break;
  2188.       case QuadNd:
  2189.          /*
  2190.           * Must be Def.
  2191.           */
  2192.          cnv_type = n->u[0].child;
  2193.          src = n->u[1].child;
  2194.          dest = n->u[3].child;
  2195.          break;
  2196.       default:
  2197.          return;   /* not a  conversion */
  2198.       }
  2199.  
  2200.    /*
  2201.     * A conversion has been found. See if it meets the criteria for
  2202.     *  issuing a warning.
  2203.     */
  2204.  
  2205.    if (src->nd_id != SymNd || !(src->u[0].sym->id_type & DrfPrm))
  2206.       return;  /* not a dereferenced parameter */
  2207.  
  2208.    if (cnv_type->nd_id == PrimryNd)
  2209.       switch (cnv_type->tok->tok_id) {
  2210.          case C_Integer:
  2211.          case C_Double:
  2212.             return;
  2213.          }
  2214.    else    /* must be exact conversion */
  2215.       if (cnv_type->tok->tok_id == C_Integer)
  2216.          return;
  2217.  
  2218.    if (dest != NULL)
  2219.       return;   /* not an in-place convertion */
  2220.  
  2221.    fprintf(stderr,
  2222.     "%s: file %s, line %d, warning: in-place conversion may or may not be\n",
  2223.       progname, cnv_type->tok->fname, cnv_type->tok->line);
  2224.    fprintf(stderr, "\tundone on subsequent failure.\n");
  2225.    }
  2226.  
  2227. /*
  2228.  * len_sel - translate a clause form a len_case statement into a C case
  2229.  *  clause.
  2230.  */
  2231. static novalue len_sel(sel, strt_prms, end_prms, indent)
  2232. struct node *sel;
  2233. int *strt_prms;
  2234. int *end_prms;
  2235. int indent;
  2236.    {
  2237.    prt_str("case ", indent);
  2238.    prt_tok(sel->tok, indent + IndentInc);           /* integer selection */
  2239.    prt_str(":", indent + IndentInc);
  2240.    rt_walk(sel->u[0].child, indent + IndentInc, 0); /* body of clase */
  2241.    ForceNl();
  2242.    prt_str("break;", indent + IndentInc);
  2243.    ForceNl();
  2244.  
  2245.    /*
  2246.     * Remember any changes to paramter locations caused by type conversions
  2247.     *  within the clause.
  2248.     */
  2249.    mrg_prmloc(end_prms);
  2250.    ld_prmloc(strt_prms);
  2251.    }
  2252.  
  2253. /*
  2254.  * rt_walk - walk the part of the syntax tree containing rtt code, producing
  2255.  *   code for the most-general version of the routine.
  2256.  */
  2257. static novalue rt_walk(n, indent, brace)
  2258. struct node *n;
  2259. int indent;
  2260. int brace;
  2261.    {
  2262.    struct token *t;
  2263.    struct node *n1;
  2264.    struct sym_entry *sym;
  2265.  
  2266.    if (n == NULL)
  2267.       return;
  2268.  
  2269.    t =  n->tok;
  2270.  
  2271.    switch (n->nd_id) {
  2272.       case PrefxNd:
  2273.          switch (t->tok_id) {
  2274.             case '{':
  2275.                /*
  2276.                 * RTL code: { <actions> }
  2277.                 */
  2278.                if (brace) 
  2279.                   tok_line(t, indent); /* just synch file name and line num */
  2280.                else
  2281.                   prt_tok(t, indent);  /* { */
  2282.                rt_walk(n->u[0].child, indent, 1);
  2283.                if (!brace)
  2284.                   prt_str("}", indent);
  2285.                break;
  2286.             case '!':
  2287.                /*
  2288.                 * RTL type-checking and conversions: ! <simple-type-check>
  2289.                 */
  2290.                prt_tok(t, indent);
  2291.                rt_walk(n->u[0].child, indent, 0);
  2292.                break;
  2293.             case Body:
  2294.             case Inline:
  2295.                /*
  2296.                 * RTL code: body { <c-code> }
  2297.                 *           inline { <c-code> }
  2298.                 */
  2299.                c_walk(n->u[0].child, indent, brace);
  2300.                break;
  2301.             }
  2302.          break;
  2303.       case BinryNd:
  2304.          switch (t->tok_id) {
  2305.             case Runerr:
  2306.                /*
  2307.                 * RTL code: runerr( <message-number> )
  2308.                 *           runerr( <message-number>, <descriptor> )
  2309.                 */
  2310.                prt_runerr(n, indent);
  2311.  
  2312.                /*
  2313.                 * Execution cannot continue on this execution path, so
  2314.                 *  it contributes nothing to the location of parameters.
  2315.                 */
  2316.                for (sym = params; sym != NULL; sym = sym->u.param_info.next)
  2317.                   if (sym->id_type & DrfPrm)
  2318.                      sym->u.param_info.cur_loc = 0;
  2319.                break;
  2320.             case And:
  2321.                /*
  2322.                 * RTL type-checking and conversions:
  2323.                 *   <type-check> && <type_check>
  2324.                 */
  2325.                chk_conj(n->u[0].child);  /* is a warning needed? */
  2326.                rt_walk(n->u[0].child, indent, 0);
  2327.                prt_str(" ", indent);
  2328.                prt_tok(t, indent);       /* && */
  2329.                prt_str(" ", indent);
  2330.                rt_walk(n->u[1].child, indent, 0);
  2331.                break;
  2332.             case Is:
  2333.                /*
  2334.                 * RTL type-checking and conversions:
  2335.                 *   is: <icon-type> ( <variable> )
  2336.                 */
  2337.                typ_asrt(n->u[0].child->tok, n->u[1].child, indent);
  2338.                break;
  2339.             }
  2340.          break;
  2341.       case ConCatNd:
  2342.          /*
  2343.           * "Glue" for two constructs.
  2344.           */
  2345.          rt_walk(n->u[0].child, indent, 0);
  2346.          rt_walk(n->u[1].child, indent, 0);
  2347.          break;
  2348.       case AbstrNd:
  2349.          /*
  2350.           * Ignore abstract type computations while producing C code
  2351.           *  for library routines.
  2352.           */
  2353.          break;
  2354.       case TrnryNd:
  2355.          switch (t->tok_id) {
  2356.             case If: {
  2357.                /*
  2358.                 * RTL code for "if" statements:
  2359.                 *  if <type-check> then <action>
  2360.                 *  if <type-check> then <action> else <action>
  2361.                 *
  2362.                 *  <type-check> may include parameter conversions that create
  2363.                 *  new scoping. It is necessary to keep track of paramter
  2364.                 *  types and locations along success and failure paths of
  2365.                 *  these conversions. The "then" and "else" actions may
  2366.                 *  also establish new scopes.
  2367.                 */
  2368.                int *then_prms = NULL;
  2369.                int *else_prms;
  2370.  
  2371.                /*
  2372.                 * Save the current parameter locations. These are in
  2373.                 *  effect on the failure path of any type conversions
  2374.                 *  in the condition of the "if".
  2375.                 */
  2376.                else_prms = new_prmloc();
  2377.                sv_prmloc(else_prms);
  2378.  
  2379.                prt_tok(t, indent);       /* if */
  2380.                prt_str(" (", indent);
  2381.                n1 = n->u[0].child;
  2382.                rt_walk(n1, indent + IndentInc, 0);   /* type check */
  2383.                prt_str(") {", indent);
  2384.  
  2385.                /*
  2386.                 * If the condition is negated, the failure path is to the "then"
  2387.                 *  and the success path is to the "else".
  2388.                 */
  2389.                if (n1->nd_id == PrefxNd && n1->tok->tok_id == '!') {
  2390.                   then_prms = else_prms;
  2391.                   else_prms = new_prmloc();
  2392.                   sv_prmloc(else_prms);
  2393.                   ld_prmloc(then_prms);
  2394.                   }
  2395.  
  2396.                rt_walk(n->u[1].child, indent + IndentInc, 1);  /* then clause */
  2397.                ForceNl();
  2398.                prt_str("}", indent + IndentInc);
  2399.  
  2400.                /*
  2401.                 * Determine if there is an else clause and merge parameter
  2402.                 *  location information from the alternate paths through
  2403.                 *  the statement.
  2404.                 */
  2405.                n1 = n->u[2].child;
  2406.                if (n1 == NULL) {
  2407.                   mrg_prmloc(else_prms);
  2408.                   ld_prmloc(else_prms);
  2409.                   }
  2410.                else {
  2411.                   if (then_prms == NULL)
  2412.                      then_prms = new_prmloc();
  2413.                   sv_prmloc(then_prms);
  2414.                   ld_prmloc(else_prms);
  2415.                   ForceNl();
  2416.                   prt_str("else {", indent);
  2417.                   rt_walk(n1, indent + IndentInc, 1);  /* else clause */
  2418.                   ForceNl();
  2419.                   prt_str("}", indent + IndentInc);
  2420.                   mrg_prmloc(then_prms);
  2421.                   ld_prmloc(then_prms);
  2422.                   }
  2423.                ForceNl();
  2424.                if (then_prms != NULL)
  2425.                   free(then_prms);
  2426.                if (else_prms != NULL)
  2427.                   free(else_prms);
  2428.                }
  2429.                break;
  2430.             case Len_case: {
  2431.                /*
  2432.                 * RTL code:
  2433.                 *   len_case <variable> of {
  2434.                 *      <integer>: <action>
  2435.                 *        ...
  2436.                 *      default: <action>
  2437.                 *      }
  2438.                 */
  2439.                int *strt_prms;
  2440.                int *end_prms;
  2441.  
  2442.                /*
  2443.                 * A case may contain parameter conversions that create new
  2444.                 *  scopes. Remember the parameter locations at the start
  2445.                 *  of the len_case statement.
  2446.                 */
  2447.                strt_prms = new_prmloc();
  2448.                sv_prmloc(strt_prms);
  2449.                end_prms = new_prmloc();
  2450.  
  2451.                n1 = n->u[0].child;
  2452.                if (!(n1->u[0].sym->id_type & VArgLen))
  2453.                   errt1(t, "len_case must select on length of vararg");
  2454.  
  2455.                /*
  2456.                 * The len_case statement is implemented as a C switch
  2457.                 *  statement.
  2458.                 */
  2459.                prt_str("switch (", indent);
  2460.                prt_var(n1, indent);
  2461.                prt_str(") {", indent);
  2462.                ForceNl();
  2463.                for (n1 = n->u[1].child; n1->nd_id == ConCatNd;
  2464.                   n1 = n1->u[0].child)
  2465.                      len_sel(n1->u[1].child, strt_prms, end_prms,
  2466.                         indent + IndentInc);
  2467.                len_sel(n1, strt_prms, end_prms, indent + IndentInc);
  2468.  
  2469.                /*
  2470.                 * Handle default clause.
  2471.                 */
  2472.                prt_str("default:", indent + IndentInc);
  2473.                ForceNl();
  2474.                rt_walk(n->u[2].child, indent + 2 * IndentInc, 0);
  2475.                ForceNl();
  2476.                prt_str("}", indent + IndentInc);
  2477.                ForceNl();
  2478.  
  2479.                /*
  2480.                 * Put into effect the location of parameters at the end
  2481.                 *  of the len_case statement.
  2482.                 */
  2483.                mrg_prmloc(end_prms);
  2484.                ld_prmloc(end_prms);
  2485.                if (strt_prms != NULL)
  2486.                   free(strt_prms);
  2487.                if (end_prms != NULL)
  2488.                   free(end_prms);
  2489.                }
  2490.                break;
  2491.             case Type_case: {
  2492.                /*
  2493.                 * RTL code:
  2494.                 *   type_case <variable> of {
  2495.                 *       <icon_type> : ... <icon_type> : <action>
  2496.                 *          ...
  2497.                 *       }
  2498.                 *
  2499.                 *   last clause may be: default: <action>
  2500.                 */
  2501.                int maybe_var;
  2502.                struct node *var;
  2503.                struct sym_entry *sym;
  2504.  
  2505.                /*
  2506.                 * If we can determine that the value being checked is
  2507.                 *  not a variable reference, we don't have to produce code
  2508.                 *  to check for that possibility.
  2509.                 */
  2510.                maybe_var = 1;
  2511.                var = n->u[0].child;
  2512.                if (var->nd_id == SymNd) {
  2513.                   sym = var->u[0].sym;
  2514.                   switch(sym->id_type) {
  2515.                      case DrfPrm:
  2516.                      case OtherDcl:
  2517.                      case TndDesc:
  2518.                      case TndStr:
  2519.                      case RsltLoc:
  2520.                         if (sym->nest_lvl > 1) {
  2521.                            /*
  2522.                             * The thing being tested is either a
  2523.                             *  dereferenced parameter or a local
  2524.                             *  descriptor which could only have been
  2525.                             *  set by a conversion which does not
  2526.                             *  produce a variable reference.
  2527.                             */
  2528.                            maybe_var = 0;
  2529.                            }
  2530.                       }
  2531.                   }
  2532.                typ_case(var, n->u[1].child, n->u[2].child, rt_walk, maybe_var,
  2533.                   indent);
  2534.                }
  2535.                break;
  2536.             case Cnv:
  2537.                /*
  2538.                 * RTL code: cnv: <type> ( <source> )
  2539.                 *           cnv: <type> ( <source> , <destination> )
  2540.                 */
  2541.                cnv_fnc(t, n->u[0].child, n->u[1].child, NULL, n->u[2].child,
  2542.                   indent);
  2543.                break;
  2544.             }
  2545.          break;
  2546.       case QuadNd:
  2547.          /*
  2548.           * RTL code: def: <type> ( <source> , <default>)
  2549.           *           def: <type> ( <source> , <default> , <destination> )
  2550.           */
  2551.          cnv_fnc(t, n->u[0].child, n->u[1].child, n->u[2].child, n->u[3].child,
  2552.             indent);
  2553.          break;
  2554.       }
  2555.    }
  2556.  
  2557. /*
  2558.  * spcl_dcls - print special declarations for tended variables, parameter
  2559.  *  conversions, and buffers.
  2560.  */
  2561. novalue spcl_dcls(op_params)
  2562. struct sym_entry *op_params; /* operation parameters or NULL */
  2563.    {
  2564.    register struct sym_entry *sym;
  2565.    struct sym_entry *sym1;
  2566.  
  2567.    /*
  2568.     * Output declarations for buffers and locations to hold conversions
  2569.     *  to C values.
  2570.     */
  2571.    spcl_start(op_params);
  2572.  
  2573.    /*
  2574.     * Determine if this operation takes a variable number of arguments.
  2575.     *  Use that information in deciding how large a tended array to
  2576.     *  declare.
  2577.     */
  2578.    varargs = (op_params != NULL && op_params->id_type & VarPrm);
  2579.    if (varargs)
  2580.       tend_ary(ntend + VArgAlwnc - 1);
  2581.    else
  2582.       tend_ary(ntend);
  2583.  
  2584.    if (varargs) {
  2585.       /*
  2586.        * This operation takes a variable number of arguments. A declaration
  2587.        *  for a tended array has been made that will usually hold them, but
  2588.        *  sometimes it is necessary to malloc() a tended array at run
  2589.        *  time. Produce code to check for this.
  2590.        */
  2591.       cur_impl->ret_flag |= DoesEFail;  /* error conversion from allocation */
  2592.       prt_str("struct tend_desc *r_tendp;", IndentInc);
  2593.       ForceNl();
  2594.       prt_str("int r_n;\n", IndentInc);
  2595.       ++line;
  2596.       ForceNl();
  2597.       prt_str("if (r_nargs <= ", IndentInc);
  2598.       fprintf(out_file, "%d)", op_params->u.param_info.param_num + VArgAlwnc);
  2599.       ForceNl();
  2600.       prt_str("r_tendp = (struct tend_desc *)&r_tend;", 2 * IndentInc);
  2601.       ForceNl();
  2602.       prt_str("else {", IndentInc);
  2603.       ForceNl();
  2604.       prt_str(
  2605.        "r_tendp = (struct tend_desc *)malloc((msize)(sizeof(struct tend_desc)",
  2606.          2 * IndentInc);
  2607.       ForceNl();
  2608.       prt_str("", 3 * IndentInc);
  2609.       fprintf(out_file, "+ (r_nargs + %d) * sizeof(struct descrip)));", 
  2610.          ntend - 2 - op_params->u.param_info.param_num);
  2611.       ForceNl();
  2612.       prt_str("if (r_tendp == NULL) {", 2 * IndentInc);
  2613.       ForceNl();
  2614.       prt_str("err_msg(305, NULL);", 3 * IndentInc);
  2615.       ForceNl();
  2616.       prt_str("return A_Resume;", 3 * IndentInc);
  2617.       ForceNl();
  2618.       prt_str("}", 3 * IndentInc);
  2619.       ForceNl();
  2620.       prt_str("}", 2 * IndentInc);
  2621.       ForceNl();
  2622.       tendstrct = "(*r_tendp)";
  2623.       }
  2624.    else
  2625.       tendstrct = "r_tend";
  2626.  
  2627.    /*
  2628.     * Produce code to initialize the tended array. These are for tended
  2629.     *  declarations and parameters.
  2630.     */
  2631.    tend_init();  /* initializations for tended declarations. */
  2632.    if (varargs) {
  2633.       /*
  2634.        * This operation takes a variable number of arguments. Produce code
  2635.        *  to dereference or copy this into its portion of the tended
  2636.        *  array.
  2637.        */
  2638.       prt_str("for (r_n = ", IndentInc);
  2639.       fprintf(out_file, "%d; r_n < r_nargs; ++r_n)",
  2640.           op_params->u.param_info.param_num);
  2641.       ForceNl();
  2642.       if (op_params->id_type & DrfPrm) {
  2643.          prt_str("deref(&r_args[r_n], &", IndentInc * 2);
  2644.          fprintf(out_file, "%s.d[r_n + %d]);", tendstrct, ntend - 1 -
  2645.             op_params->u.param_info.param_num);
  2646.          }
  2647.       else {
  2648.          prt_str(tendstrct, IndentInc * 2);
  2649.          fprintf(out_file, ".d[r_n + %d] = r_args[r_n];", ntend - 1 -
  2650.             op_params->u.param_info.param_num);
  2651.          }
  2652.       ForceNl();
  2653.       sym = op_params->u.param_info.next;
  2654.       }
  2655.    else
  2656.       sym = op_params; /* no variable part of arg list */
  2657.  
  2658.    /*
  2659.     * Go through the fixed part of the parameter list, producing code
  2660.     *  to copy/dereference parameters into the tended array.
  2661.     */
  2662.    while (sym != NULL) {
  2663.       /*
  2664.        * A there may be identifiers for dereferenced and/or undereferenced
  2665.        *  versions of a paramater. If there are both, sym1 references the
  2666.        *  second identifier.
  2667.        */
  2668.       sym1 = sym->u.param_info.next;
  2669.       if (sym1 != NULL && sym->u.param_info.param_num !=
  2670.          sym1->u.param_info.param_num)
  2671.             sym1 = NULL;    /* the next entry is not for the same parameter */
  2672.  
  2673.       /*
  2674.        * If there are not enough arguments to supply a value for this
  2675.        *  parameter, set it to the null value.
  2676.        */
  2677.       prt_str("if (", IndentInc);
  2678.       fprintf(out_file, "r_nargs > %d) {", sym->u.param_info.param_num);
  2679.       ForceNl();
  2680.       parm_tnd(sym);
  2681.       if (sym1 != NULL) {
  2682.          ForceNl();
  2683.          parm_tnd(sym1);
  2684.          }
  2685.       ForceNl();
  2686.       prt_str("} else {", IndentInc);
  2687.       ForceNl();
  2688.       prt_str(tendstrct, IndentInc * 2);
  2689.       fprintf(out_file, ".d[%d].dword = D_Null;", sym->t_indx);
  2690.       if (sym1 != NULL) {
  2691.          ForceNl();
  2692.          prt_str(tendstrct, IndentInc * 2);
  2693.          fprintf(out_file, ".d[%d].dword = D_Null;", sym1->t_indx);
  2694.          }
  2695.       ForceNl();
  2696.       prt_str("}", 2 * IndentInc);
  2697.       ForceNl();
  2698.       if (sym1 == NULL)
  2699.          sym = sym->u.param_info.next;
  2700.       else
  2701.          sym = sym1->u.param_info.next;
  2702.       }
  2703.  
  2704.    /*
  2705.     * Finish setting up the tended array structure and link it into the tended
  2706.     *  list.
  2707.     */
  2708.    if (ntend != 0) {
  2709.       prt_str(tendstrct, IndentInc);
  2710.       if (varargs)
  2711.          fprintf(out_file, ".num = %d + Max(r_nargs - %d, 0);", ntend - 1,
  2712.             op_params->u.param_info.param_num);
  2713.       else
  2714.          fprintf(out_file, ".num = %d;", ntend);
  2715.       ForceNl();
  2716.       prt_str(tendstrct, IndentInc);
  2717.       prt_str(".previous = tend;", IndentInc);
  2718.       ForceNl();
  2719.       prt_str("tend = (struct tend_desc *)&", IndentInc);
  2720.       fprintf(out_file, "%s;", tendstrct);
  2721.       ForceNl();
  2722.       }
  2723.    }
  2724.  
  2725. /*
  2726.  * spcl_start - do initial work for outputing special declarations. Output
  2727.  *  declarations for buffers and locations to hold conversions to C values.
  2728.  *  Determine what tended locations are needed for parameters.
  2729.  */
  2730. static novalue spcl_start(op_params)
  2731. struct sym_entry *op_params;
  2732.    {
  2733.    ForceNl();
  2734.    if (n_tmp_str > 0) {
  2735.       prt_str("char r_sbuf[", IndentInc);
  2736.       fprintf(out_file, "%d][MaxCvtLen];", n_tmp_str);
  2737.       ForceNl();
  2738.       }
  2739.    if (n_tmp_cset > 0) {
  2740.       prt_str("struct b_cset r_cbuf[", IndentInc);
  2741.       fprintf(out_file, "%d];", n_tmp_cset);
  2742.       ForceNl();
  2743.       }
  2744.    if (tend_lst == NULL)
  2745.       ntend = 0;
  2746.    else
  2747.       ntend = tend_lst->t_indx + 1;
  2748.    parm_locs(op_params); /* see what parameter conversion there are */
  2749.    }
  2750.  
  2751. /*
  2752.  * tend_ary - write struct containing array of tended descriptors.
  2753.  */
  2754. static novalue tend_ary(n)
  2755. int n;
  2756.    {
  2757.    if (n == 0)
  2758.       return;
  2759.    prt_str("struct {", IndentInc);
  2760.    ForceNl();
  2761.    prt_str("struct tend_desc *previous;", 2 * IndentInc);
  2762.    ForceNl();
  2763.    prt_str("int num;", 2 * IndentInc);
  2764.    ForceNl();
  2765.    prt_str("struct descrip d[", 2 * IndentInc);
  2766.    fprintf(out_file, "%d];", n);
  2767.    ForceNl();
  2768.    prt_str("} r_tend;\n", 2 * IndentInc);
  2769.    ++line;
  2770.    ForceNl();
  2771.    }
  2772.  
  2773. /*
  2774.  * tend_init - produce code to initialize entries in the tended array
  2775.  *  corresponding to tended declarations. Default initializations are
  2776.  *  supplied when there is none in the declaration.
  2777.  */
  2778. static novalue tend_init()
  2779.    {
  2780.    register struct init_tend *tnd;
  2781.  
  2782.    for (tnd = tend_lst; tnd != NULL; tnd = tnd->next) {
  2783.       switch (tnd->init_typ) {
  2784.          case TndDesc:
  2785.             /*
  2786.              * Simple tended declaration.
  2787.              */
  2788.             prt_str(tendstrct, IndentInc);
  2789.             if (tnd->init == NULL)
  2790.                fprintf(out_file, ".d[%d].dword = D_Null;", tnd->t_indx);
  2791.             else {
  2792.                fprintf(out_file, ".d[%d] = ", tnd->t_indx);
  2793.                c_walk(tnd->init, 2 * IndentInc, 0);
  2794.                prt_str(";", 2 * IndentInc);
  2795.                }
  2796.             break;
  2797.          case TndStr:
  2798.             /*
  2799.              * Tended character pointer.
  2800.              */
  2801.             prt_str(tendstrct, IndentInc);
  2802.             if (tnd->init == NULL)
  2803.                fprintf(out_file, ".d[%d] = emptystr;", tnd->t_indx);
  2804.             else {
  2805.                fprintf(out_file, ".d[%d].dword = 0;", tnd->t_indx);
  2806.                ForceNl();
  2807.                prt_str(tendstrct, IndentInc);
  2808.                fprintf(out_file, ".d[%d].vword.sptr = ", tnd->t_indx);
  2809.                c_walk(tnd->init, 2 * IndentInc, 0);
  2810.                prt_str(";", 2 * IndentInc);
  2811.                }
  2812.             break;
  2813.          case TndBlk:
  2814.             /*
  2815.              * A tended block pointer of some kind.
  2816.              */
  2817.             prt_str(tendstrct, IndentInc);
  2818.             if (tnd->init == NULL)
  2819.                fprintf(out_file, ".d[%d] = nullptr;", tnd->t_indx);
  2820.             else {
  2821.                fprintf(out_file, ".d[%d].dword = F_Ptr | F_Nqual;",tnd->t_indx);
  2822.                ForceNl();
  2823.                prt_str(tendstrct, IndentInc);
  2824.                fprintf(out_file, ".d[%d].vword.bptr = (union block *)",
  2825.                    tnd->t_indx);
  2826.                c_walk(tnd->init, 2 * IndentInc, 0);
  2827.                prt_str(";", 2 * IndentInc);
  2828.                }
  2829.             break;
  2830.          }
  2831.       ForceNl();
  2832.       }
  2833.    }
  2834.  
  2835. /*
  2836.  * parm_tnd - produce code to put a parameter in its tended location.
  2837.  */
  2838. static novalue parm_tnd(sym)
  2839. struct sym_entry *sym;
  2840.    {
  2841.    /*
  2842.     * A parameter may either be dereferenced into its tended location
  2843.     *  or copied.
  2844.     */
  2845.    if (sym->id_type & DrfPrm) {
  2846.       prt_str("deref(&r_args[", IndentInc * 2);
  2847.       fprintf(out_file, "%d], &%s.d[%d]);", sym->u.param_info.param_num,
  2848.          tendstrct, sym->t_indx);
  2849.       }
  2850.    else {
  2851.       prt_str(tendstrct, IndentInc * 2);
  2852.       fprintf(out_file, ".d[%d] = r_args[%d];", sym->t_indx,
  2853.          sym->u.param_info.param_num);
  2854.       }
  2855.    }
  2856.  
  2857. /*
  2858.  * parm_locs - determine what locataions are needed to hold parameters and
  2859.  *  their conversions. Produce declarations for the C_integer and C_double
  2860.  *  locations.
  2861.  */
  2862. static novalue parm_locs(op_params)
  2863. struct sym_entry *op_params;
  2864.    {
  2865.    struct sym_entry *next_parm;
  2866.  
  2867.    /*
  2868.     * Parameters are stored in reverse order: Recurse down the list
  2869.     *  and preform processing on the way back.
  2870.     */
  2871.    if (op_params == NULL)
  2872.       return;
  2873.    next_parm = op_params->u.param_info.next;
  2874.    parm_locs(next_parm);
  2875.  
  2876.    /*
  2877.     * For interpreter routines, extra tended descriptors are only needed
  2878.     *  when both dereferenced and undereferenced values are requested.
  2879.     */
  2880.    if (iconx_flg && (next_parm == NULL ||
  2881.       op_params->u.param_info.param_num != next_parm->u.param_info.param_num))
  2882.       op_params->t_indx = -1;
  2883.    else
  2884.       op_params->t_indx = ntend++;
  2885.    if (op_params->u.param_info.non_tend & PrmInt) {
  2886.       prt_str("C_integer r_i", IndentInc);
  2887.       fprintf(out_file, "%d;", op_params->u.param_info.param_num);
  2888.       ForceNl();
  2889.       }
  2890.    if (op_params->u.param_info.non_tend & PrmDbl) {
  2891.       prt_str("double r_d", IndentInc);
  2892.       fprintf(out_file, "%d;", op_params->u.param_info.param_num);
  2893.       ForceNl();
  2894.       }
  2895.    }
  2896.  
  2897. /*
  2898.  * real_def - see if a declaration really defines storage.
  2899.  */
  2900. static int real_def(n)
  2901. struct node *n;
  2902.    {
  2903.    struct node *dcl_lst;
  2904.  
  2905.    dcl_lst = n->u[1].child;
  2906.    /*
  2907.     * If no variables are being defined this must be a tag declaration.
  2908.     */
  2909.    if (dcl_lst == NULL)
  2910.       return 0;
  2911.    
  2912.    if (only_proto(dcl_lst))
  2913.       return 0;
  2914.  
  2915.    if (tdef_or_extr(n->u[0].child))
  2916.       return 0;
  2917.  
  2918.    return 1;
  2919.    }
  2920.  
  2921. /*
  2922.  * only_proto - see if this declarator list contains only function prototypes.
  2923.  */
  2924. static int only_proto(n)
  2925. struct node *n;
  2926.    {
  2927.    switch (n->nd_id) {
  2928.       case CommaNd:
  2929.          return only_proto(n->u[0].child) & only_proto(n->u[1].child);
  2930.       case ConCatNd:
  2931.          /*
  2932.           * Optional pointer.
  2933.           */
  2934.          return only_proto(n->u[1].child);
  2935.       case BinryNd:
  2936.          switch (n->tok->tok_id) {
  2937.             case '=':
  2938.                return only_proto(n->u[0].child);
  2939.             case '[':
  2940.                /*
  2941.                 * At this point, assume array declarator is not part of
  2942.                 *  prototype.
  2943.                 */
  2944.                return 0;
  2945.             case ')':
  2946.                /*
  2947.                 * Prototype (or forward declaration).
  2948.                 */
  2949.                return 1;
  2950.             }
  2951.       case PrefxNd:
  2952.          /*
  2953.           * Parenthisized.
  2954.           */
  2955.          return only_proto(n->u[0].child);
  2956.       case PrimryNd:
  2957.          /*
  2958.           * At this point, assume it is not a prototype.
  2959.           */
  2960.          return 0;
  2961.       }
  2962.    err1("rtt internal error detected in function only_proto()");
  2963.    /* NOTREACHED */
  2964.    }
  2965.  
  2966. /*
  2967.  * tdef_or_extr - see if this is a typedef or extern.
  2968.  */
  2969. static int tdef_or_extr(n)
  2970. struct node *n;
  2971.    {
  2972.    switch (n->nd_id) {
  2973.       case LstNd:
  2974.          return tdef_or_extr(n->u[0].child) | tdef_or_extr(n->u[1].child);
  2975.       case BinryNd:
  2976.          /*
  2977.           * struct, union, or enum.
  2978.           */
  2979.          return 0;
  2980.       case PrimryNd:
  2981.          if (n->tok->tok_id == Extern || n->tok->tok_id == Typedef)
  2982.             return 1;
  2983.          else
  2984.             return 0;
  2985.       }
  2986.    err1("rtt internal error detected in function tdef_or_extr()");
  2987.    /* NOTREACHED */
  2988.    }
  2989.  
  2990. /*
  2991.  * dclout - output an ordinary global C declaration.
  2992.  */
  2993. novalue dclout(n)
  2994. struct node *n;
  2995.    {
  2996.    if (!enable_out)
  2997.       return;        /* output disabled */
  2998.    if (real_def(n))
  2999.       def_fnd = 1;   /* this declaration defines a run-time object */
  3000.    c_walk(n, 0, 0);
  3001.    free_tree(n);
  3002.    }
  3003.  
  3004. /*
  3005.  * fncout - output code for a C function.
  3006.  */
  3007. novalue fncout(head, prm_dcl, block)
  3008. struct node *head;
  3009. struct node *prm_dcl;
  3010. struct node *block;
  3011.    {
  3012.    if (!enable_out)
  3013.       return;       /* output disabled */
  3014.  
  3015.    def_fnd = 1;     /* this declaration defines a run-time object */
  3016.  
  3017.    nxt_sbuf = 0;    /* clear number of string buffers */
  3018.    nxt_cbuf = 0;    /* clear number of cset buffers */
  3019.  
  3020.    /*
  3021.     * Output the function header and the parameter declarations.
  3022.     */
  3023.    fnc_head = head;
  3024.    c_walk(head, 0, 0);
  3025.    prt_str(" ",  0);
  3026.    c_walk(prm_dcl, 0, 0);
  3027.    prt_str(" ", 0);
  3028.  
  3029.    /* 
  3030.     * Handle outer block.
  3031.     */
  3032.    prt_tok(block->tok, IndentInc);          /* { */
  3033.    c_walk(block->u[0].child, IndentInc, 0); /* non-tended declarations */
  3034.    spcl_dcls(NULL);                         /* tended declarations */
  3035.    no_ret_val = 1;
  3036.    c_walk(block->u[2].child, IndentInc, 0); /* statement list */
  3037.    if (ntend != 0 && no_ret_val) {
  3038.       /*
  3039.        * This function contains no return statements with values, assume
  3040.        *  that the programmer is using the implicit return at the end
  3041.        *  of the function and update the tending of descriptors.
  3042.        */
  3043.       untend(IndentInc);
  3044.       }
  3045.    ForceNl();
  3046.    prt_str("}", IndentInc);
  3047.    ForceNl();
  3048.  
  3049.    /*
  3050.     * free storage.
  3051.     */
  3052.    free_tree(head);
  3053.    free_tree(prm_dcl);
  3054.    free_tree(block);
  3055.    pop_cntxt();
  3056.    clr_def();
  3057.    }
  3058.  
  3059. /*
  3060.  * defout - output operation definitions (except for constant keywords)
  3061.  */
  3062. novalue defout(n)
  3063. struct node *n;
  3064.    {
  3065.    struct sym_entry *sym, *sym1;
  3066.  
  3067.    if (!enable_out)
  3068.       return;       /* output disabled */
  3069.  
  3070.    nxt_sbuf = 0;
  3071.    nxt_cbuf = 0;
  3072.  
  3073.    /*
  3074.     * Somewhat different code is produced for the interpreter and compiler.
  3075.     */
  3076.    if (iconx_flg)
  3077.       interp_def(n);
  3078.    else
  3079.       comp_def(n);
  3080.  
  3081.    free_tree(n);
  3082.    /*
  3083.     * The declarations for the declare statement are not associated with
  3084.     *  any compound statement and must be freed here.
  3085.     */
  3086.    sym = dcl_stk->tended;
  3087.    while (sym != NULL) {
  3088.       sym1 = sym;
  3089.       sym = sym->u.tnd_var.next;
  3090.       free_sym(sym1);
  3091.       }
  3092.    while (decl_lst != NULL) {
  3093.       sym1 = decl_lst;
  3094.       decl_lst = decl_lst->u.declare_var.next;
  3095.       free_sym(sym1);
  3096.       }
  3097.    op_type = OrdFunc;
  3098.    pop_cntxt();
  3099.    clr_def();
  3100.    }
  3101.  
  3102. /*
  3103.  * comp_def - output code for the compiler for operation definitions.
  3104.  */
  3105. static novalue comp_def(n)
  3106. struct node *n;
  3107.    {
  3108. #ifdef Rttx
  3109.    fprintf(stdout, "rtt was compiled to only support the intepreter, use -x\n");
  3110.    exit(ErrorExit);
  3111. #else                    /* Rttx */
  3112.    struct sym_entry *sym;
  3113.    struct node *n1;
  3114.    FILE *f_save;
  3115.    char buf1[5];
  3116.    char buf[MaxFileName];
  3117.    char *cname;
  3118.    long min_result;
  3119.    long max_result;
  3120.    int ret_flag;
  3121.    int resume;
  3122.    char *name;
  3123.  
  3124.    f_save = out_file;
  3125.  
  3126.    /*
  3127.     * Note if the result location is explicitly referenced and note
  3128.     *  how it is accessed in the generated code.
  3129.     */
  3130.    cur_impl->use_rslt = sym_lkup(str_rslt)->u.referenced;
  3131.    rslt_loc = "(*r_rslt)";
  3132.  
  3133.    /*
  3134.     * In several contexts, letters are used to distiguish kinds of operations.
  3135.     */
  3136.    switch (op_type) {
  3137.       case Function:
  3138.          lc_letter = 'f';
  3139.          uc_letter = 'F';
  3140.          break;
  3141.       case Keyword:
  3142.          lc_letter = 'k';
  3143.          uc_letter = 'K';
  3144.          break;
  3145.       case Operator:
  3146.          lc_letter = 'o';
  3147.          uc_letter = 'O';
  3148.       }
  3149.    prfx1 = cur_impl->prefix[0];
  3150.    prfx2 = cur_impl->prefix[1];
  3151.  
  3152.    if (op_type != Keyword) {
  3153.       /*
  3154.        * First pass through the operation: produce most general routine.
  3155.        */
  3156.       fnc_ret = RetSig;  /* most general routine always returns a signal */
  3157.  
  3158.       /*
  3159.        * Compute the file name in which to output the function.
  3160.        */
  3161.       sprintf(buf1, "%c_%c%c", lc_letter, prfx1, prfx2);
  3162.       cname = salloc(makename(buf, SourceDir, buf1, CSuffix));
  3163.       if ((out_file = fopen(cname, "w")) == NULL)
  3164.          err2("cannot open output file", cname);
  3165.          
  3166.       prologue(); /* output standard comments and preprocessor directives */
  3167.  
  3168.       /*
  3169.        * Output function header that corresponds to standard calling
  3170.        *  convesions. The function name is constructed from the letter
  3171.        *  for the operation type, the prefix that makes the function
  3172.        *  name unique, and the name of the operation.
  3173.        */
  3174.       fprintf(out_file, "int %c%c%c_%s(r_nargs, r_args, r_rslt, r_s_cont)\n",
  3175.          uc_letter, prfx1, prfx2, cur_impl->name);
  3176.       fprintf(out_file, "int r_nargs;\n");
  3177.       fprintf(out_file, "dptr r_args;\n");
  3178.       fprintf(out_file, "dptr r_rslt;\n");
  3179.       fprintf(out_file, "continuation r_s_cont;");
  3180.       fname = cname;
  3181.       line = 12;
  3182.       ForceNl();
  3183.       prt_str("{", IndentInc);
  3184.       ForceNl();
  3185.  
  3186.       /*
  3187.        * Output ordinary declarations from declare clause.
  3188.        */
  3189.       for (sym = decl_lst; sym != NULL; sym = sym->u.declare_var.next) {
  3190.          c_walk(sym->u.declare_var.tqual, IndentInc, 0);
  3191.          prt_str(" ", IndentInc);
  3192.          c_walk(sym->u.declare_var.dcltor, IndentInc, 0);
  3193.          if ((n1 = sym->u.declare_var.init) != NULL) {
  3194.             prt_str(" = ", IndentInc);
  3195.             c_walk(n1, IndentInc, 0);
  3196.             }
  3197.          prt_str(";", IndentInc);
  3198.          }
  3199.  
  3200.       /*
  3201.        * Output code for special declarations along with code to initial
  3202.        *  them. This includes buffers and tended locations for parameters
  3203.        *  and tended variables.
  3204.        */
  3205.       spcl_dcls(params);
  3206.  
  3207.       rt_walk(n, IndentInc, 0);  /* body of operation */
  3208.  
  3209.       ForceNl();
  3210.       prt_str("}\n", IndentInc);
  3211.       fclose(out_file);
  3212.       put_c_fl(cname, 1);  /* note name of output file for operation */
  3213.       }
  3214.  
  3215.    /*
  3216.     * Second pass through operation: produce in-line code and special purpose
  3217.     *  routines.
  3218.     */
  3219.    for (sym = params; sym != NULL; sym = sym->u.param_info.next)
  3220.       if (sym->id_type & DrfPrm)
  3221.          sym->u.param_info.cur_loc = PrmTend;  /* reset location of parameter */
  3222.    in_line(n);
  3223.  
  3224.    /*
  3225.     * Insure that the fail/return/suspend statements are consistant
  3226.     *  with the result sequence indicated.
  3227.     */
  3228.    min_result = cur_impl->min_result;
  3229.    max_result = cur_impl->max_result;
  3230.    ret_flag = cur_impl->ret_flag;
  3231.    resume = cur_impl->resume;
  3232.    name = cur_impl->name;
  3233.    if (min_result == NoRsltSeq && ret_flag & (DoesFail|DoesRet|DoesSusp))
  3234.       err2(name,
  3235.          ": result sequence of {}, but fail, return, or suspend present");
  3236.    if (min_result != NoRsltSeq && ret_flag == 0)
  3237.       err2(name,
  3238.          ": result sequence indicated, no fail, return, or suspend present");
  3239.    if (min_result == 0 && !(ret_flag & DoesFail))
  3240.       err2(name,
  3241.          ": result sequence indicates possible failure, but no fail statement");
  3242.    if (max_result != NoRsltSeq) {
  3243.       if (max_result == 0 && ret_flag & (DoesRet|DoesSusp))
  3244.          err2(name,
  3245.             ": result seqence of 0 length, but return or suspend present");
  3246.       if (max_result != 0 && !(ret_flag & (DoesRet | DoesSusp)))
  3247.          err2(name,
  3248.             ": result sequence length > 0, but no return or suspend present");
  3249.       if ((max_result == UnbndSeq || max_result > 1 || resume) &&
  3250.          !(ret_flag & DoesSusp))
  3251.          err2(name,
  3252.             ": result sequence indicates suspension, but no suspend present");
  3253.       if ((max_result != UnbndSeq && max_result <= 1 && !resume) &&
  3254.          ret_flag & DoesSusp)
  3255.          err2(name,
  3256.             ": result sequence indicates no suspension, but suspend present");
  3257.       }
  3258.    if (min_result != NoRsltSeq && max_result != UnbndSeq &&
  3259.       min_result > max_result)
  3260.       err2(name, ": minimum result sequence length greater than maximum");
  3261.  
  3262.    out_file = f_save;
  3263. #endif                    /* Rttx */
  3264.    }
  3265.  
  3266. /*
  3267.  * interp_def - output code for the interpreter for operation definitions.
  3268.  */
  3269. static novalue interp_def(n)
  3270. struct node *n;
  3271.    {
  3272.    struct sym_entry *sym;
  3273.    struct node *n1;
  3274.    int nparms;
  3275.    int has_underef;
  3276.    char letter;
  3277.    char *name;
  3278.  
  3279.    /*
  3280.     * Note how result location is accessed in generated code.
  3281.     */
  3282.    rslt_loc = "r_args[0]";
  3283.  
  3284.    /*
  3285.     * Determine if the operation has any undereferenced parameters.
  3286.     */
  3287.    has_underef = 0;
  3288.    for (sym = params; sym != NULL; sym = sym->u.param_info.next)
  3289.       if (sym->id_type  & RtParm) {
  3290.          has_underef = 1;
  3291.          break;
  3292.          }
  3293.  
  3294.    /*
  3295.     * Determine the nuber of parameters. A negative value is used
  3296.     *  to indicate an operation that takes a variable number of
  3297.     *  arguments.
  3298.     */
  3299.    if (params == NULL)
  3300.       nparms = 0;
  3301.    else {
  3302.       nparms = params->u.param_info.param_num + 1;
  3303.       if (params->id_type & VarPrm)
  3304.          nparms = -nparms;
  3305.       }
  3306.  
  3307.    fnc_ret = RetSig;  /* interpreter routine always returns a signal */
  3308.    name = cur_impl->name;
  3309.  
  3310.    /*
  3311.     * Determine what letter is used to prefix the operation name.
  3312.     */
  3313.    switch (op_type) {
  3314.       case Function:
  3315.          letter = 'X';
  3316.          break;
  3317.       case Keyword:
  3318.          letter = 'K';
  3319.          break;
  3320.       case Operator:
  3321.          letter = 'O';
  3322.          }
  3323.  
  3324.    fprintf(out_file, "\n");
  3325.    if (op_type != Keyword) {
  3326.       /*
  3327.        * Output prototype. Operations taking a variable number of arguments
  3328.        *   have an extra parameter: the number of arguments.
  3329.        */
  3330.       fprintf(out_file, "int %c%s Params((", letter, name);
  3331.       if (params != NULL && (params->id_type & VarPrm))
  3332.          fprintf(out_file, "int r_nargs, ");
  3333.       fprintf(out_file, "dptr r_args));\n");
  3334.       ++line;
  3335.  
  3336.       /*
  3337.        * Output procedure block.
  3338.        */
  3339.       switch (op_type) {
  3340.          case Function:
  3341.             fprintf(out_file, "FncBlock(%s, %d, %d)\n\n", name, nparms, 
  3342.                (has_underef ? -1 : 0));
  3343.             ++line;
  3344.             break;
  3345.          case Operator:
  3346.             if (strcmp(cur_impl->op,"\\") == 0)
  3347.                fprintf(out_file, "OpBlock(%s, %d, \"%s\", 0)\n\n", name, nparms,
  3348.                   "\\\\");
  3349.             else
  3350.                fprintf(out_file, "OpBlock(%s, %d, \"%s\", 0)\n\n", name, nparms,
  3351.                   cur_impl->op);
  3352.             ++line;
  3353.          }
  3354.       }
  3355.  
  3356.    /*
  3357.     * Output fuction header. Operations taking a variable number of arguments
  3358.     *   have an extra parameter: the number of arguments.
  3359.     */
  3360.    fprintf(out_file, "int %c%s(", letter, name);
  3361.    if (params != NULL && (params->id_type & VarPrm))
  3362.       fprintf(out_file, "r_nargs, ");
  3363.    fprintf(out_file, "r_args)\n");
  3364.    ++line;
  3365.    if (params != NULL && (params->id_type & VarPrm)) {
  3366.       fprintf(out_file, "int r_nargs;\n");
  3367.       ++line;
  3368.       }
  3369.    fprintf(out_file, "dptr r_args;");
  3370.    ++line;
  3371.    ForceNl();
  3372.    prt_str("{", IndentInc);
  3373.       
  3374.    /*
  3375.     * Output ordinary declarations from the declare clause.
  3376.     */
  3377.    ForceNl();
  3378.    for (sym = decl_lst; sym != NULL; sym = sym->u.declare_var.next) {
  3379.       c_walk(sym->u.declare_var.tqual, IndentInc, 0);
  3380.       prt_str(" ", IndentInc);
  3381.       c_walk(sym->u.declare_var.dcltor, IndentInc, 0);
  3382.       if ((n1 = sym->u.declare_var.init) != NULL) {
  3383.          prt_str(" = ", IndentInc);
  3384.          c_walk(n1, IndentInc, 0);
  3385.          }
  3386.       prt_str(";", IndentInc);
  3387.       }
  3388.  
  3389.    /*
  3390.     * Output special declarations and initial processing.
  3391.     */
  3392.    tendstrct = "r_tend";
  3393.    spcl_start(params);
  3394.    tend_ary(ntend);
  3395.    if (has_underef && params != NULL && params->id_type == (VarPrm | DrfPrm))
  3396.       prt_str("int r_n;\n", IndentInc);
  3397.    tend_init();
  3398.  
  3399.    /*
  3400.     * See which parameters need to be dereferenced. If all are dereferenced,
  3401.     *  it is done by before the routine is called.
  3402.     */
  3403.    if (has_underef) {
  3404.       sym = params;
  3405.       if (sym != NULL && sym->id_type & VarPrm) {
  3406.          if (sym->id_type & DrfPrm) {
  3407.             /*
  3408.              * There is a variable part of the parameter list and it
  3409.              *  must be dereferenced.
  3410.              */
  3411.             prt_str("for (r_n = ", IndentInc);
  3412.             fprintf(out_file, "%d; r_n <= r_nargs; ++r_n)",
  3413.                 sym->u.param_info.param_num + 1);
  3414.             ForceNl();
  3415.             prt_str("Deref(r_args[r_n]);", IndentInc * 2);
  3416.             ForceNl();
  3417.             }
  3418.          sym = sym->u.param_info.next;
  3419.          }
  3420.  
  3421.       /*
  3422.        * Produce code to dereference any fixed parameters that need to be.
  3423.        */
  3424.       while (sym != NULL) {
  3425.          if (sym->id_type & DrfPrm) {
  3426.             /*
  3427.              * Tended index of -1 indicates that the parameter can be
  3428.              *  dereferened in-place (this is the usual case).
  3429.              */
  3430.             if (sym->t_indx == -1) {
  3431.                prt_str("Deref(r_args[", IndentInc * 2);
  3432.                fprintf(out_file, "%d]);", sym->u.param_info.param_num + 1);
  3433.                }
  3434.             else {
  3435.                prt_str("deref(&r_args[", IndentInc * 2);
  3436.                fprintf(out_file, "%d], &r_tend.d[%d]);",
  3437.                   sym->u.param_info.param_num + 1, sym->t_indx);
  3438.                }
  3439.             }
  3440.          ForceNl();
  3441.          sym = sym->u.param_info.next;
  3442.          }
  3443.       }
  3444.  
  3445.    /*
  3446.     * Finish setting up the tended array structure and link it into the tended
  3447.     *  list.
  3448.     */
  3449.    if (ntend != 0) {
  3450.       prt_str("r_tend.num = ", IndentInc);
  3451.       fprintf(out_file, "%d;", ntend);
  3452.       ForceNl();
  3453.       prt_str("r_tend.previous = tend;", IndentInc);
  3454.       ForceNl();
  3455.       prt_str("tend = (struct tend_desc *)&r_tend;", IndentInc);
  3456.       ForceNl();
  3457.       }
  3458.  
  3459.    rt_walk(n, IndentInc, 0);  /* body of operation */
  3460.    ForceNl();
  3461.    prt_str("}\n", IndentInc);
  3462.    }
  3463.  
  3464. /*
  3465.  * keyconst - produce code for a constant keyword.
  3466.  */
  3467. novalue keyconst(t)
  3468. struct token *t;
  3469.    {
  3470.    struct il_code *il;
  3471.    int n;
  3472.  
  3473.    if (iconx_flg) {
  3474.       /*
  3475.        * For the interpreter, output a C function implementing the keyword.
  3476.        */
  3477.       rslt_loc = "r_args[0]";  /* result location */
  3478.  
  3479.       fprintf(out_file, "\n");
  3480.       fprintf(out_file, "int K%s(r_args)\n", cur_impl->name);
  3481.       fprintf(out_file, "dptr r_args;");
  3482.       line += 2;
  3483.       ForceNl();
  3484.       prt_str("{", IndentInc);
  3485.       ForceNl();
  3486.       switch (t->tok_id) {
  3487.          case StrLit:
  3488.             prt_str(rslt_loc, IndentInc);
  3489.             prt_str(".vword.sptr = \"", IndentInc);
  3490.             n = prt_i_str(out_file, t->image, (int)strlen(t->image));
  3491.             prt_str("\";", IndentInc);
  3492.             ForceNl();
  3493.             prt_str(rslt_loc, IndentInc);
  3494.             fprintf(out_file, ".dword = %d;", n);
  3495.             break;
  3496.          case CharConst:
  3497.             prt_str("static struct b_cset cset_blk = ", IndentInc);
  3498.             cset_init(out_file, bitvect(t->image, (int)strlen(t->image)));
  3499.             ForceNl();
  3500.             prt_str(rslt_loc, IndentInc);
  3501.             prt_str(".dword = D_Cset;", IndentInc);
  3502.             ForceNl();
  3503.             prt_str(rslt_loc, IndentInc);
  3504.             prt_str(".vword.bptr = (union block *)&cset_blk;", IndentInc);
  3505.             break;
  3506.          case DblConst:
  3507.             prt_str("static struct b_real real_blk = {T_Real, ", IndentInc);
  3508.             fprintf(out_file, "%s};", t->image);
  3509.             ForceNl();
  3510.             prt_str(rslt_loc, IndentInc);
  3511.             prt_str(".dword = D_Real;", IndentInc);
  3512.             ForceNl();
  3513.             prt_str(rslt_loc, IndentInc);
  3514.             prt_str(".vword.bptr = (union block *)&real_blk;", IndentInc);
  3515.             break;
  3516.          case IntConst:
  3517.             prt_str(rslt_loc, IndentInc);
  3518.             prt_str(".dword = D_Integer;", IndentInc);
  3519.             ForceNl();
  3520.             prt_str(rslt_loc, IndentInc);
  3521.             prt_str(".vword.integr = ", IndentInc);
  3522.             prt_str(t->image, IndentInc);
  3523.             prt_str(";", IndentInc);
  3524.             break;
  3525.          }
  3526.       ForceNl();
  3527.       prt_str("return A_Continue;", IndentInc);
  3528.       ForceNl();
  3529.       prt_str("}\n", IndentInc);
  3530.       ++line;
  3531.       ForceNl();
  3532.       }
  3533.    else {
  3534.       /*
  3535.        * For the compiler, make an entry in the data base for the keyword.
  3536.        */
  3537.       cur_impl->use_rslt = 0;
  3538.    
  3539.       il = new_il(IL_Const, 2);
  3540.       switch (t->tok_id) {
  3541.          case StrLit:
  3542.             il->u[0].n = TypStr;
  3543.             il->u[1].s = (char *)alloc((unsigned int)(strlen(t->image) + 3));
  3544.             sprintf(il->u[1].s, "\"%s\"", t->image);
  3545.             break;
  3546.          case CharConst:
  3547.             il->u[0].n = TypCset;
  3548.             il->u[1].s = (char *)alloc((unsigned int)(strlen(t->image) + 3));
  3549.             sprintf(il->u[1].s, "'%s'", t->image);
  3550.             break;
  3551.          case DblConst:
  3552.             il->u[0].n = TypReal;
  3553.             il->u[1].s = t->image;
  3554.             break;
  3555.          case IntConst:
  3556.             il->u[0].n = TypInt;
  3557.             il->u[1].s = t->image;
  3558.             break;
  3559.          }
  3560.       cur_impl->in_line = il;
  3561.       }
  3562.  
  3563.    /*
  3564.     * Reset the translator and free storage.
  3565.     */
  3566.    op_type = OrdFunc;
  3567.    free_t(t);
  3568.    pop_cntxt();
  3569.    clr_def();
  3570.    }
  3571.  
  3572. /*
  3573.  * keepdir - A preprocessor directive to be kept has been encountered.
  3574.  *   If it is #passthru, print just the body of the directive, otherwise
  3575.  *   print the whole thing.
  3576.  */
  3577. novalue keepdir(t)
  3578. struct token *t;
  3579.    {
  3580.    char *s;
  3581.  
  3582.    tok_line(t, 0);
  3583.    s = t->image;
  3584.    if (strncmp(s, "#passthru", 9) == 0)
  3585.       s = s + 10;
  3586.    fprintf(out_file, "%s\n", s);
  3587.    line += 1;
  3588.    }
  3589.  
  3590. /*
  3591.  * prologue - print stanard comments and preprocessor directives at the
  3592.  *   start of an output file.
  3593.  */
  3594. novalue prologue()
  3595.    {
  3596.    id_comment(out_file);
  3597.    fprintf(out_file, "%s", compiler_def);
  3598.    fprintf(out_file, "#include \"%s\"\n\n", inclname);
  3599.    }
  3600.